Document Format#

Kodemo uses a JSON document format to save and load content. To get a better understanding of how that JSON is structured, let's build out a document from the ground up.

Title & Version#

At the root of our document you'll find a document title as well as a version number. The version number refers to the Kodemo Editor version that was used to author the document.

Story#

The story represents the main body text for a document. It is stored as HTML and supports all of the standard HTML tags for formatting.

Subjects#

The subjects are the tabs to the right of the Kodemo interface, i.e. the code/images/etc you're writing about. Each subject has a unique key that is used when linking to it from the story.

Subject Index#

The subjectIndex is an array of subject keys in the order that we want subjects to appear to the end user. If a subject is missing from the index, it will appear last after all indexed subjects.

Subject Type & Name#

Each subject must have a type and name. The type can be either code, image, or iframe. The subject name is used to represent this subject in the Kodemo UI.

Versions#

The content for our subjects is stored as one or more versions. Versions are used to represent multiple variants of the same content, for example code that changes in multiple steps.

Some subjects, such as images, require only one version. Others, like code, support multiple versions and will carry out unique transitions when the end user navigates between those versions.

All versions have unique keys. They contain slightly different data depending on what type of content they represent.

Version Index#

Just like subjects, versions have their own versionIndex. This is used to control the order of appearance of versions in the interface.

Effects#

Effects are used to create a relationship between keywords in your story and your subjects. More specifically, they make a subject appear in view as you progress through the story.

Effects are inline tags with the following data attributes:

data-effect-id [required]
A unique identifier for the effect.

data-effect-subject [required]
ID of the subject this effect should activate.

data-effect-version
ID of the subject version to activate.

data-effect-type="invisible"
Effect are visible as inline highlights in the story. If you'd like to add an effect that isn't highlighted in the story, set this attribute to "invisible".

data-effect-payload
This is used to provide context-specific data to effects, such as which lines of code that should be highlighted or which part of an image that should be focused.

{
"title": "reveal.js",
"version": "0.1.9",
"story": "<h1 id=\"configuring-revealjs\"><span data-effect-id=\"effect-1666724847439-32\" data-effect-type=\"invisible\" data-effect-subject=\"2b397a6a\" data-effect-version=\"85e79b90\">Configuring reveal.js</span></h1><h2 id=\"initialization\"><span data-effect-id=\"effect-1666722886164-1\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\">Initialization</span></h2><p>The most common reveal.js use case is to have a single presentation which covers the full viewport. As of 4.0 we also support running multiple presentations in parallel on the same page as well as including the library as an ES module.</p><p>If you only have a single presentation on the page we recommend initializing reveal.js using the global Reveal object. The <span data-effect-id=\"effect-1666722886164-2\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;3-5&quot;}\">Reveal.initialize</span> method accepts one argument; a reveal.js config object.</p><p>The initialize method returns a promise which will resolve as soon as the presentation is ready and can be interacted with via the API.</p><h2 id=\"initializing-plugins\"><span data-effect-id=\"effect-1666722886164-3\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"a688e818\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;2-3, 7&quot;}\">Initializing Plugins</span></h2><p>Normally when you initialize reveal.js you will be including one or two its plugins. This is done by passing plugin instances via the <code>plugins</code> configuration option.</p><h3 id=\"ready-event\">Ready Event</h3><p>If you want to interact with a plugin, you will need to wait for the <code><span data-effect-id=\"effect-1666724617286-28\" data-effect-subject=\"699bbe77\" data-effect-version=\"f8d224e3\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;5-8&quot;}\">ready</span></code> event to fire. This event fires once reveal.js and its plugins are fully loaded and initialized. We strongly recommend w
}

{
"title": "reveal.js",
"version": "0.1.9",
"story": "<h1 id=\"configuring-revealjs\"><span data-effect-id=\"effect-1666724847439-32\" data-effect-type=\"invisible\" data-effect-subject=\"2b397a6a\" data-effect-version=\"85e79b90\">Configuring reveal.js</span></h1><h2 id=\"initialization\"><span data-effect-id=\"effect-1666722886164-1\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\">Initialization</span></h2><p>The most common reveal.js use case is to have a single presentation which covers the full viewport. As of 4.0 we also support running multiple presentations in parallel on the same page as well as including the library as an ES module.</p><p>If you only have a single presentation on the page we recommend initializing reveal.js using the global Reveal object. The <span data-effect-id=\"effect-1666722886164-2\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;3-5&quot;}\">Reveal.initialize</span> method accepts one argument; a reveal.js config object.</p><p>The initialize method returns a promise which will resolve as soon as the presentation is ready and can be interacted with via the API.</p><h2 id=\"initializing-plugins\"><span data-effect-id=\"effect-1666722886164-3\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"a688e818\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;2-3, 7&quot;}\">Initializing Plugins</span></h2><p>Normally when you initialize reveal.js you will be including one or two its plugins. This is done by passing plugin instances via the <code>plugins</code> configuration option.</p><h3 id=\"ready-event\">Ready Event</h3><p>If you want to interact with a plugin, you will need to wait for the <code><span data-effect-id=\"effect-1666724617286-28\" data-effect-subject=\"699bbe77\" data-effect-version=\"f8d224e3\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;5-8&quot;}\">ready</span></code> event to fire. This event fires once reveal.js and its plugins are fully loaded and initialized. We strongly recommend w
"subjectIndex": [
"2b397a6a",
"699bbe77",
"de5e71f1",
"1ca8c87e"
],
"subjects": {
"699bbe77": {
"name": "initialization.html",
"type": "code",
"versions": {
"8f082a96": {
"value": "<script src=\"dist/reveal.js\"></script>\n<script src=\"plugins/notes/notes.js\"></script>\n<script src=\"plugins/markdown/markdown.js\"></script>\n<script>\n Reveal.on('ready', () => {\n if( Reveal.hasPlugin('notes') ) {\n // Now that plugins are ready, we can interact with them \n Reveal.getPlugin('notes').open();\n }\n });\n Reveal.initialize({\n transition: 'none'\n plugins: [ RevealNotes, RevealMarkdown ]\n });\n</script>"
},
"f8d224e3": {
"value": "<script src=\"dist/reveal.js\"></script>\n<script src=\"plugins/notes/notes.js\"></script>\n<script src=\"plugins/markdown/markdown.js\"></script>\n<script>\n Reveal.on('ready', () => {\n // Now that plugins are ready, we can interact with them \n Reveal.getPlugin('notes').open();\n });\n Reveal.initialize({\n transition: 'none'\n plugins: [ RevealNotes, RevealMarkdown ]\n });\n</script>"
},
"20cbdef7": {
"value": "<script src=\"dist/reveal.js\"></script>\n<script>\n Reveal.initialize({\n transition: 'none'\n });\n</script>"
},
"b49c13ea": {
"value": "<script src=\"dist/reveal.js\"></script>\n<script>\n Reveal.initialize({\n transition: 'none'\n }).then(() => {\n // reveal.js is ready\n });\n</script>"
},
"a688e818": {
"value": "<script src=\"dist/reveal.js\"></script>\n<script src=\"plugins/notes/notes.js\"></script>\n<script src=\"plugins/markdown/markdown.js\"></script>\n<script>\n Reveal.initialize({\n transition: 'none'\n plugins: [ RevealNotes, RevealMarkdown ]\n });\n</script>"
}
}
},
"1ca8c87e": {
"name": "themes.png",
"type": "image",
"versions": {
{
"title": "reveal.js",
"version": "0.1.9",
"story": "<h1 id=\"configuring-revealjs\"><span data-effect-id=\"effect-1666724847439-32\" data-effect-type=\"invisible\" data-effect-subject=\"2b397a6a\" data-effect-version=\"85e79b90\">Configuring reveal.js</span></h1><h2 id=\"initialization\"><span data-effect-id=\"effect-1666722886164-1\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\">Initialization</span></h2><p>The most common reveal.js use case is to have a single presentation which covers the full viewport. As of 4.0 we also support running multiple presentations in parallel on the same page as well as including the library as an ES module.</p><p>If you only have a single presentation on the page we recommend initializing reveal.js using the global Reveal object. The <span data-effect-id=\"effect-1666722886164-2\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;3-5&quot;}\">Reveal.initialize</span> method accepts one argument; a reveal.js config object.</p><p>The initialize method returns a promise which will resolve as soon as the presentation is ready and can be interacted with via the API.</p><h2 id=\"initializing-plugins\"><span data-effect-id=\"effect-1666722886164-3\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"a688e818\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;2-3, 7&quot;}\">Initializing Plugins</span></h2><p>Normally when you initialize reveal.js you will be including one or two its plugins. This is done by passing plugin instances via the <code>plugins</code> configuration option.</p><h3 id=\"ready-event\">Ready Event</h3><p>If you want to interact with a plugin, you will need to wait for the <code><span data-effect-id=\"effect-1666724617286-28\" data-effect-subject=\"699bbe77\" data-effect-version=\"f8d224e3\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;5-8&quot;}\">ready</span></code> event to fire. This event fires once reveal.js and its plugins are fully loaded and initialized. We strongly recommend w
"subjectIndex": [
"2b397a6a",
"699bbe77",
"de5e71f1",
"1ca8c87e"
],
"subjects": {
"699bbe77": {
},
"1ca8c87e": {
},
"de5e71f1": {
},
"2b397a6a": {
}
}
}

{
"title": "reveal.js",
"version": "0.1.9",
"story": "<h1 id=\"configuring-revealjs\"><span data-effect-id=\"effect-1666724847439-32\" data-effect-type=\"invisible\" data-effect-subject=\"2b397a6a\" data-effect-version=\"85e79b90\">Configuring reveal.js</span></h1><h2 id=\"initialization\"><span data-effect-id=\"effect-1666722886164-1\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\">Initialization</span></h2><p>The most common reveal.js use case is to have a single presentation which covers the full viewport. As of 4.0 we also support running multiple presentations in parallel on the same page as well as including the library as an ES module.</p><p>If you only have a single presentation on the page we recommend initializing reveal.js using the global Reveal object. The <span data-effect-id=\"effect-1666722886164-2\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;3-5&quot;}\">Reveal.initialize</span> method accepts one argument; a reveal.js config object.</p><p>The initialize method returns a promise which will resolve as soon as the presentation is ready and can be interacted with via the API.</p><h2 id=\"initializing-plugins\"><span data-effect-id=\"effect-1666722886164-3\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"a688e818\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;2-3, 7&quot;}\">Initializing Plugins</span></h2><p>Normally when you initialize reveal.js you will be including one or two its plugins. This is done by passing plugin instances via the <code>plugins</code> configuration option.</p><h3 id=\"ready-event\">Ready Event</h3><p>If you want to interact with a plugin, you will need to wait for the <code><span data-effect-id=\"effect-1666724617286-28\" data-effect-subject=\"699bbe77\" data-effect-version=\"f8d224e3\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;5-8&quot;}\">ready</span></code> event to fire. This event fires once reveal.js and its plugins are fully loaded and initialized. We strongly recommend w
"subjects": {
"699bbe77": {
},
"1ca8c87e": {
},
"de5e71f1": {
},
"2b397a6a": {
}
}
}

{
"title": "reveal.js",
"version": "0.1.9",
"story": "<h1 id=\"configuring-revealjs\"><span data-effect-id=\"effect-1666724847439-32\" data-effect-type=\"invisible\" data-effect-subject=\"2b397a6a\" data-effect-version=\"85e79b90\">Configuring reveal.js</span></h1><h2 id=\"initialization\"><span data-effect-id=\"effect-1666722886164-1\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\">Initialization</span></h2><p>The most common reveal.js use case is to have a single presentation which covers the full viewport. As of 4.0 we also support running multiple presentations in parallel on the same page as well as including the library as an ES module.</p><p>If you only have a single presentation on the page we recommend initializing reveal.js using the global Reveal object. The <span data-effect-id=\"effect-1666722886164-2\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;3-5&quot;}\">Reveal.initialize</span> method accepts one argument; a reveal.js config object.</p><p>The initialize method returns a promise which will resolve as soon as the presentation is ready and can be interacted with via the API.</p><h2 id=\"initializing-plugins\"><span data-effect-id=\"effect-1666722886164-3\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"a688e818\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;2-3, 7&quot;}\">Initializing Plugins</span></h2><p>Normally when you initialize reveal.js you will be including one or two its plugins. This is done by passing plugin instances via the <code>plugins</code> configuration option.</p><h3 id=\"ready-event\">Ready Event</h3><p>If you want to interact with a plugin, you will need to wait for the <code><span data-effect-id=\"effect-1666724617286-28\" data-effect-subject=\"699bbe77\" data-effect-version=\"f8d224e3\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;5-8&quot;}\">ready</span></code> event to fire. This event fires once reveal.js and its plugins are fully loaded and initialized. We strongly recommend w
"subjectIndex": [
"2b397a6a",
"699bbe77",
"de5e71f1",
"1ca8c87e"
],
"subjects": {
"699bbe77": {
"name": "initialization.html",
"type": "code",
},
"1ca8c87e": {
"name": "themes.png",
"type": "image",
},
"de5e71f1": {
"name": "configuration.js",
"type": "code",
},
"2b397a6a": {
"name": "reveal.png",
"type": "image",
}
}
}

{
"title": "reveal.js",
"version": "0.1.9",
"story": "<h1 id=\"configuring-revealjs\"><span data-effect-id=\"effect-1666724847439-32\" data-effect-type=\"invisible\" data-effect-subject=\"2b397a6a\" data-effect-version=\"85e79b90\">Configuring reveal.js</span></h1><h2 id=\"initialization\"><span data-effect-id=\"effect-1666722886164-1\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\">Initialization</span></h2><p>The most common reveal.js use case is to have a single presentation which covers the full viewport. As of 4.0 we also support running multiple presentations in parallel on the same page as well as including the library as an ES module.</p><p>If you only have a single presentation on the page we recommend initializing reveal.js using the global Reveal object. The <span data-effect-id=\"effect-1666722886164-2\" data-effect-subject=\"699bbe77\" data-effect-version=\"20cbdef7\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;3-5&quot;}\">Reveal.initialize</span> method accepts one argument; a reveal.js config object.</p><p>The initialize method returns a promise which will resolve as soon as the presentation is ready and can be interacted with via the API.</p><h2 id=\"initializing-plugins\"><span data-effect-id=\"effect-1666722886164-3\" data-effect-type=\"invisible\" data-effect-subject=\"699bbe77\" data-effect-version=\"a688e818\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;2-3, 7&quot;}\">Initializing Plugins</span></h2><p>Normally when you initialize reveal.js you will be including one or two its plugins. This is done by passing plugin instances via the <code>plugins</code> configuration option.</p><h3 id=\"ready-event\">Ready Event</h3><p>If you want to interact with a plugin, you will need to wait for the <code><span data-effect-id=\"effect-1666724617286-28\" data-effect-subject=\"699bbe77\" data-effect-version=\"f8d224e3\" data-effect-payload=\"{&quot;codeHighlights&quot;:&quot;5-8&quot;}\">ready</span></code> event to fire. This event fires once reveal.js and its plugins are fully loaded and initialized. We strongly recommend w
"subjectIndex": [
"2b397a6a",
"699bbe77",
"de5e71f1",
"1ca8c87e"
],
"subjects": {
"699bbe77": {
"name": "initialization.html",
"type": "code",
"versionIndex": [
"20cbdef7",
"b49c13ea",
"a688e818",
"f8d224e3",
"8f082a96"
],
"versions": {
"8f082a96": {
"value": "<script src=\"dist/reveal.js\"></script>\n<script src=\"plugins/notes/notes.js\"></script>\n<script src=\"plugins/markdown/markdown.js\"></script>\n<script>\n Reveal.on('ready', () => {\n if( Reveal.hasPlugin('notes') ) {\n // Now that plugins are ready, we can interact with them \n Reveal.getPlugin('notes').open();\n }\n });\n Reveal.initialize({\n transition: 'none'\n plugins: [ RevealNotes, RevealMarkdown ]\n });\n</script>"
},
"f8d224e3": {
"value": "<script src=\"dist/reveal.js\"></script>\n<script src=\"plugins/notes/notes.js\"></script>\n<script src=\"plugins/markdown/markdown.js\"></script>\n<script>\n Reveal.on('ready', () => {\n // Now that plugins are ready, we can interact with them \n Reveal.getPlugin('notes').open();\n });\n Reveal.initialize({\n transition: 'none'\n plugins: [ RevealNotes, RevealMarkdown ]\n });\n</script>"
},
"20cbdef7": {
"value": "<script src=\"dist/reveal.js\"></script>\n<script>\n Reveal.initialize({\n transition: 'none'\n });\n</script>"
},
"b49c13ea": {
"value": "<script src=\"dist/reveal.js\"></script>\n<script>\n Reveal.initialize({\n transition: 'none'\n }).then(() => {\n // reveal.js is ready\n });\n</script>"
},
"a688e818": {
"value": "<script src=\"dist/reveal.js\"></script>\n<script src=\"plugins/notes/notes.js\"></script>\n<script src=\"plugins/markdown/markdown.js\"></script>\n<script>\n Reveal.initialize({\n transition: 'none'\n plugins: [ RevealNotes, RevealMarkdown ]\n });\n</script>"
Here's how an <span
data-effect-id="1"
data-effect-subject="699bbe77"
data-effect-version="f8d224e3">effect</span> can appear the story HTML.