Getting started tutorial

This short guide will walk you through the steps required to create a new Kolibri channel by using a content integration script (a.k.a. sushi chef script) based on the ricecooker framework. We’ll write a Python script that creates a simple channel containing one PDF file, and run this script to upload the PDF to Kolibri Studio so it can then be imported in Kolibri.


The software tools developed by the Learning Equality content team have food-related code names. Content integration scripts are called “sushi chefs” since they perform the detail-oriented task of taking external educational resources (🐟), packaging them as individual Kolibri content nodes (🍣), and organizing them neatly into Kolibri channels (🍱).


If you haven’t done so already, go through the steps on the installation page to install the ricecooker Python package and other system prerequisites.

Obtaining a Studio access token

You’ll need a Kolibri Studio Access Token to create channels using ricecooker scripts. To obtain this token:

  1. Create an account on Kolibri Studio

  2. Navigate to the Settings page on Kolibri Studio.

  3. Copy the given access token to a safe place on your computer.

You must pass the token on the command line as --token=<your-access-token> when calling your chef script. Alternatively, you can create a file to store your token and pass in the command line argument --token=path/to/studiotoken.txt.

Video overview

Watch this video tutorial to learn how to create a new content integration script and set the required channel metadata fields like CHANNEL_SOURCE_DOMAIN and CHANNEL_SOURCE_ID.


Creating a sushichef script

In a new folder on your computer, create a file called with the code contents shown below. Alternatively you can use the “Save as” option on this link to achieve the same result. We’ll use this simple example of a content integration script for this tutorial.

#!/usr/bin/env python
from ricecooker.chefs import SushiChef
from ricecooker.classes.files import DocumentFile
from ricecooker.classes.licenses import get_license
from ricecooker.classes.nodes import DocumentNode
from ricecooker.classes.nodes import TopicNode

class SimpleChef(SushiChef):
    channel_info = {
        "CHANNEL_TITLE": "Potatoes info channel",
        "CHANNEL_SOURCE_DOMAIN": "<>",  # where content comes from
        "CHANNEL_SOURCE_ID": "<unique id for the channel>",  # CHANGE ME!!!
        "CHANNEL_LANGUAGE": "en",  # le_utils language code
        "CHANNEL_THUMBNAIL": "",  # (optional)
        "CHANNEL_DESCRIPTION": "What is this channel about?",  # (optional)

    def construct_channel(self, **kwargs):
        channel = self.get_channel(**kwargs)
        potato_topic = TopicNode(title="Potatoes!", source_id="<potatoes_id>")
        document_node = DocumentNode(
            title="Growing potatoes",
            description="An article about growing potatoes on your rooftop.",
            license=get_license("CC BY", copyright_holder="University of Alberta"),
        return channel

if __name__ == "__main__":
    Run this script on the command line using:
        python  --token=YOURTOKENHERE9139139f3a23232
    simple_chef = SimpleChef()

The code above is the equivalent of a “Hello, World!” content integration script based on the ricecooker framework that will create a Kolibri channel with a single topic node (Folder), and put a single PDF content node inside that folder.

As you can tell from the above code sample, most of the code in a content integration script is concerned with setting the right metadata for files, content nodes, topics nodes (folders), and the overall channel. This will be the running theme when you work on content integration scripts.


You need to modify the value of CHANNEL_SOURCE_ID before you continue, otherwise you’ll get an error when you run the script in the next step. The combination of CHANNEL_SOURCE_DOMAIN and CHANNEL_SOURCE_ID serve to create the channel’s unique ID. If you use the same values as an already existing channel, you will either get a permissions error, or if you have editing permissions, you could overwrite the channel contents. Therefore, you want to be careful to use different values from the default ones used in the sample code.

Running the sushichef script

You can run a chef script by calling it on the command line:

python  --token=<your-access-token>

The most important argument when running a chef script is --token, which is used to pass in the Studio Access Token and authenticates you in Kolibri Studio. To see all the ricecooker command line options, run python -h. For more details about running chef scripts see the chefops page.


If you get an error when running this command, make sure you have replaced <your-access-token> with the token you obtained from Kolibri Studio. Also make sure you’ve changed the value of channel_info['CHANNEL_SOURCE_ID'] instead of using the value in the sample code.

If the command succeeds, you should see something like this printed in your terminal:

In method. args={'command': 'uploadchannel', 'token': '<your-access-token>', 'update': False, 'resume': False, 'stage': True, 'publish': False} options={}
Logged in with username
Ricecooker v0.6.42 is up-to-date.

* Starting channel build process *

Calling construct_channel...
   Setting up initial channel structure...
   Validating channel structure...
      Potatoes info channel (ChannelNode): 2 descendants
         Potatoes! (TopicNode): 1 descendant
            Growing potatoes (DocumentNode): 1 file
   Tree is valid

Downloading files...
Processing content...
    --- Downloaded 3641693a88b37e8d0484c340a83f9364.pdf
    --- Downloaded 290c80ed7ce4cf117772f29dda76413c.jpg
   All files were successfully downloaded

Checking if files exist on Kolibri Studio...
    Got file diff for 2 out of 2 files
Uploading files...
Uploading 0 new file(s) to Kolibri Studio...

Creating channel...
Creating tree on Kolibri Studio...
   Creating channel Potatoes info channel
    (0 of 2 uploaded)    Processing Potatoes info channel (ChannelNode)
    (1 of 2 uploaded)       Processing Potatoes! (TopicNode)
       All nodes were created successfully.
Upload time: 0.896938s

DONE: Channel created at

Congratulations, you put the potatoes on the internet! You’re probably already a legend in Ireland!

What just happened?

As you can tell from the above messages, running a involves all kinds of steps that are orchestrated by the ricecooker framework:
  • The channel structure is created based on the output of the method construct_channel of the SimpleChef class

  • The tree structure and metadata are validated

  • All referenced files are downloaded locally (saved in the storage directory)

  • New files are uploaded to Kolibri Studio (in the above case no new files are uploaded because the files already exist on Studio from a previous run)

  • The channel structure and metadata is uploaded to Kolibri Studio

  • A link is printed for you to view the channel draft you just uploaded

If you’re interested, you can read this page to learn about the tech details behind these steps, but the details are not important for now. Let’s continue to follow your channel’s journey by clicking the Kolibri Studio link.

View your channel in Kolibri Studio

At the end of the chef run the complete channel (files and metadata) will be uploaded to a “draft version” of the channel called a “staging tree”. Use the DEPLOY button in the Studio web interface to take your channel out of “draft mode.” This step is normally important for reviewing changes between the new draft version and the current version of the channel.

The next step is to PUBLISH your channel using the button on Studio. The PUBLISH action exports all the channel metadata and files in the format that is used by Kolibri and so it is needed in order to import you channel in Kolibri.

At the end of the PUBLISH step, you will be able to see the channel token associated with your channel, which is a short two-word string that you’ll use in the next step. You’ll also receive an email notification telling you when the channel has finished publishing.


Running the chef script with the command arguments --deploy --publish will perform both the DEPLOY and PUBLISH actions after the chef run completes. This combination of arguments can be used for testing and development, but never for “production” channels, which must be reviewed before deploying.

Import your channel in Kolibri

The final step is to IMPORT your channel into Kolibri using the channel token you obtained after the Kolibri Studio PUBLISH step finished.

Congratulations! Thanks to your Python skills and perseverence through this multi-step process involving three software systems, you finally have access to your content in the offline-capable Kolibri Learning Platform.

This topic node “Potatoes!” is nice to look at no doubt, but it feels kind of empty. Not to worry—in the next step of this tutorial we’ll learn how to add more nodes to your channel. Before that let’s do a quick recap of what we’ve learned thus far.

Recap and next steps

We can summarize the entire process we the Kolibri channel followed through the three parts of the Kolibri ecosystem using the following diagram:

sushichef(ricecooker)       Kolibri Studio             Kolibri
UPLOADCHANNEL------->-------DEPLOY+PUBLISH------>------IMPORT (using channel token)

I know it seems like a complicated process, but you’ll get used to it after going through it a couple of times. All the steps represent necessary complexity. The automated extraction and packaging of source materials ricecooker into Kolibri channels provides the “raw materials” on which educators can build by reusing and remixing in Kolibri Studio. Ultimately the technical effort you invest in creating content integration scripts will benefit learners and teachers all around the world, this week and for years to come. So get the metadata right!

As your next step for learning about Kolibri channels, we propose an optional, non-technical activity to get to know Kolibri Studio better. After that we’ll resume the ricecooker training with the hands-on tutorial. If you’re in a hurry, and want to skip ahead to API reference docs pages, check out content nodes and files.

Try the manual upload (optional)

Redo the steps from this tutorial but this time using the Kolibri Studio web interface. The manual upload process (Integration Method 1) is can be described as follows:

Kolibri Studio             Kolibri
UPLOAD+PUBLISH------>------IMPORT (using channel token)

Login to Kolibri Studio and try these steps:

  1. Create a new channel

  2. Add a topic node to your channel

  3. Add content by uploading a PDF document (note which metadata fields are required and which are optional)

  4. Use the ADD > Import from Channels feature to import the Growing potatoes document node from the Potatoes info channel.

  5. PUBLISH your channel (a new channel token will be generated).

  6. IMPORT your channel in Kolibri using the channel token.

Most of the channel creation operations steps you can do using ricecooker, you can also do through the Kolibri Studio web interface—in both cases you’re creating Kolibri channels, that can be PUBLISH-ed and used offline in Kolibri.


Channels created using a content integration script (ricecooker channels), cannot be modified manually through the Kolibri Studio web interface. This is because manual changes would get overwritten and lost on next chef runs. If you want to make manual edits/tweaks to the channel, you can create a “derivative channel” and import the content from the ricecooker channel using the ADD > Import from Channels feature as in step 4 above.

Hands-on tutorial

Now that we have a working example of a simple chef, we’re ready to extend it by adding other kinds of nodes (nutritional groups) and files (ingredients). The next section will take you through a hands-on tutorial where you’ll learn how to use the different content kinds and file types supported by the ricecooker framework to create Kolibri channels.