Interactive code cells

What would you say if Jupyter Notebooks could ➀ support any programming language, ➁ have no hidden state, and ➂ have a native look and feel for any article or blog post?

Well, I've just shipped something like that! With the latest codapi-js feature called code cells, you can create a series of interactive code snippets that depend on each other and execute them without leaving your browser.

Let's look at an example.

Code cells

Suppose we are writing an SQL tutorial using PostgreSQL. First, let's create an employees table:

create table employees (
  id integer primary key,
  name varchar(50),
  department varchar(10),
  salary integer
);

Then insert some employee data:

insert into employees
(id, name, department, salary)
values
(11, 'Diane', 'hr', 70),
(12, 'Bob', 'hr', 78),
(21, 'Emma', 'it', 84),
(22, 'Grace', 'it', 90),
(23, 'Henry', 'it', 104),
(31, 'Cindy', 'sales', 96),
(32, 'Dave', 'sales', 96),
(33, 'Alice', 'sales', 100);

Finally, rank the employees according to their salaries in each department:

select
  department as dep,
  dense_rank() over w as rank,
  name, salary
from employees
window w as (
  partition by department
  order by salary desc
)
order by department, rank;

As you can probably see, the insert snippet depends on the create snippet, while the select snippet depends on both create and insert, forming a dependency chain:

create ← insert ← select

This is how the snippets work:

  • When you run the insert snippet, it automatically creates the table before inserting the data.
  • When you run the select snippet, it automatically creates the table and inserts the records before selecting the data.

The dependencies do not have to be linear, they can form an (acyclic) graph. Suppose we want to describe the table schema:

\d employees;

The describe snippet does not need table data, so it can depend directly on the create snippet:

create ← insert ← select
   ↖
  describe

More complex dependency graphs are also possible, as long as there are no cycles:

create ← insert-1 ← select
       ↖ insert-2 ↙

You probably get the idea.

Implementation

Back to our example. Suppose we started with two static code examples — create and insert:

create table employees (
  id integer primary key,
  name varchar(50),
  department varchar(10),
  salary integer
);
insert into employees
(id, name, department, salary)
values
(11, 'Diane', 'hr', 70),
(12, 'Bob', 'hr', 78),
(21, 'Emma', 'it', 84);

First, we make them interactive by adding codapi-snippets.

➀ Create:

```sql
create table employees (
  id integer primary key,
  name varchar(50),
  department varchar(10),
  salary integer
);
```

<codapi-snippet id="create.sql" sandbox="postgres" editor="basic">
</codapi-snippet>

➁ Insert:

```sql
insert into employees
(id, name, department, salary)
values
(11, 'Diane', 'hr', 70),
(12, 'Bob', 'hr', 78),
(21, 'Emma', 'it', 84);
```

<codapi-snippet id="insert.sql" sandbox="postgres" editor="basic">
</codapi-snippet>

Then we make insert dependent on create by adding a depends-on attribute:

<codapi-snippet id="insert.sql" sandbox="postgres" editor="basic"
    depends-on="create.sql">
</codapi-snippet>

The rest is automatic!

Behind the scenes, codapi-snippet calls a codapi server (either a cloud or self-hosted instance) so it can run any programming language, database or software you've configured.

No hidden state

As you know, Jupyter notebooks are stateful — that is, they store the state of variables between cell invocations. This can be a good thing for prototyping, but not for documentation or explanation.

The last thing I want as a reader is code examples that fail or behave oddly because they were run out of order. Or because I didn't run some cells. Or because I changed a cell and didn't re-run it.

Codapi code cells, unlike Jupyter's, have no hidden state. Instead, they execute the whole chain of dependencies as needed to ensure that the reader gets a consistent result.

Summary

Codapi provides an easy way to create interactive examples in technical documentation. It gets even easier with code cells, which allow declarative dependencies between snippets of code.

Give it a try!

About CodapiCodapi serverSnippet widget

 Subscribe to keep up with new posts.