@coursekata/ckcode

ckcode: Power up your webpage with live Jupyter cells

ckcode provides a simple way for your users to run code on a Jupyter server from within your webpage. If you would like to see it in action, check out the user-guide.

The app works by providing users with a simple code module that they can type code into, relating their execution requests to a server, and then displaying the output. It requires a server capable of handling these requests, which you can either setup yourself or run via a BinderHub (see our backend Binder setup for an example).

This app was developed for CourseKata Statistics and Data Science, an innovative interactive online textbook for teaching introductory statistics and data science in colleges, universities, and high schools. Part of CourseKata’s Better Book Project, we are leveraging research and student data to guide continuous improvement of online learning resources.

This page is not a user-guide

If you are a learner using a book that uses ckcode or an author writing specifications for code exercises, you should head to the the user-guide. The page you are on currently is intended for developers.

Installation

Currently, this package is only available via our private GitHub repository. First, you need to configure npm to use the GitHub registry in addition to the standard NPM registry:

  1. Authenticate to GitHub Packages. For more information, see "Authenticating to GitHub Packages."

  2. In the same directory as your package.json file, create or edit an .npmrc file to include a line associating this package's organization scope with the GitHub registry.

    @coursekata:registry=https://npm.pkg.github.com
    
  3. Install as you would normally. For example, from the command-line:

    npm install @coursekata/ckcode
    

Bundling for the Browser

This package is designed to be used in the browser. To use it, you will need to bundle it with your other code. The recommended way to do this is with Webpack. The demo app has a minimal Webpack configuration that you can use as a starting point.

Configuration

Configuration has two main parts, the top level config for the code-cells, and the config for the underlying Jupyter server session (currently there is support for a normal Jupyter server session or a Jupyter server running on BinderHub). The general form of the config is

const config = {
...baseCodeCellConfig,
session: {
...sessionConfig,
},
};

Collecting Data

To collect data on how users are interacting with your cell (for example, to grade student responses), use the events fired by the <code-cell> elements. Here is an example showing how you can log every run for a particular cell:

const element = document.getElementById("code-exercise-01");
element.addEventListener("run", (event) => {
console.log(event.detail);
});

Events

All events emitted from code-cell elements implement the CustomEvent interface. The data conveyed by the event (i.e. the payload) is passed via the event's detail property. All events have the following common properties in their payload:

  • cellId (string) the id of the cell
  • timestamp (Date) the time the event was fired
  • event (string) the name of the event

In addition to these common properties, some events have additional properties. Here is a description of the events and their payloads:

  • start
    • Fires when the user first clicks into the cell on the page (once per page load).
    • Payload is null.
  • run
    • Fires when the user clicks the Run button.
    • Payload is an object with a single property
      • content (string) containing the submitted code string.
  • submit
    • Fires when the user clicks the Submit button.
    • Payload is an object with a single property
      • content (string) containing the submitted code string.
  • feedback:
    • Fires when the feedback is returned after the submit has been processed.
    • Payload is an object with two properties
      • correct (boolean) indicating whether the response passed the tests
      • content (string) with the feedback shown to the user, formatted as markdown
  • solution
    • Fires when the user clicks the button to show the solution.
    • Payload is null.
  • reset
    • Fires when the user clicks the button to reset the cell.
    • Payload is null.

Legacy Support

As of version 2.1.0, ckcode supports the legacy configuration from the 0.x versions of the package. This is to support existing books that use the old configuration. The legacy configuration is deprecated and will be removed in a future version.

Because the legacy app was exposed as a global variable, you can still use it in your code. The global variable is still called ckcode and contains the previous CKCode key which is now essentially a facade that configures the app with the legacy configuration:

import "@coursekata/ckcode";
ckcode.CKCode(legacyConfig);

IMPORTANT: Bundling and Polyfills

Versions 0.x bundled the app dependencies with the package. This is no longer the case. If you wish to retain the old behavior you should use the companion distributable version of the package @coursekata/ckcode-dist. This package is a drop-in replacement for the old package and will bundle the dependencies with the package.

Additionally, if you are using the older versions you are probably not using polyfills for lit or web components. You should probably add these to your project:

npm install lit @webcomponents/webcomponentsjs

And then import the polyfills in your code:

// polyfills for older browsers
import "@webcomponents/webcomponentsjs/webcomponents-loader.js";
import "lit/polyfill-support.js";

// main app imports
import "@coursekata/ckcode-dist";

// configure and start the app
ckcode.CKCode(legacyConfig);

Acknowledgements

ckcode began as a fork of Thebe.

Generated using TypeDoc