Skip to content

Latest commit

 

History

46 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

Interactive SCORM Codelab Generator

This repository contains a Node-based tool for generating SCORM-compatible interactive learning modules from a single Markdown (.md) file.
The generated output is a SCORM ZIP that can be uploaded directly into an LMS such as Blackboard.

Example of app running

Features:

  • Step-by-step modules that learners can complete.
  • Modules are marked as complete as students progress through.
  • Images, codeblocks, hyperlinks and most markdown syntax (including GitHub callout support).
  • Inline quizzes using :::quiz blocks with SCORM answer persistence.
  • Light/dark mode.
  • Automatically formatted codeblocks.
  • Tracking/saving progress. Upon re-opening the module, learners are asked if they would like to continue where they left off.
  • optional Bonus task support
  • Optional contextual key-term definitions from keywords.md, with related-term navigation.

Overview

Each SCORM module is generated from one Markdown file, which defines:

  • The module title
  • An optional cover page
  • Step-by-step learning content
  • Code blocks, callouts, lists, links, and images
  • Optional SCORM metadata (description, course code)

The generator outputs SCORM ZIP artifacts to:

./interactive-codelab/scorm/*.zip

Each ZIP represents one complete SCORM module.


Project Structure (Relevant Paths)

interactive-codelab/
├── content/
│   └── module.md          # Markdown file used to generate the module
├── public/
│   └── assets/            # Image assets referenced by the markdown
├── scorm/
│   └── *.zip              # Generated SCORM packages

Generating a SCORM Package

Sample data is present in the project for the purpoose of testing. Before generating a new module, reset the content and assets directories.

1. Clean existing content

Delete the contents of the following directories:

./interactive-codelab/public/assets/*
./interactive-codelab/content/*

2. Copy assets

Copy any image assets used by your module into:

./interactive-codelab/public/assets/

3. Prepare the Markdown file

  • Copy your Markdown file into:
./interactive-codelab/content/
  • Rename it to:
module.md
  • Optionally add a keywords.md file alongside module.md. Each definition begins with a level-one heading, and its content continues until the next level-one heading, so it supports the same Markdown features as lesson content.

  • Declare related-term bubbles with a dedicated HTML comment on its own line. Separate term names with commas; names that also have a # definition become clickable bubbles:

    # Android Studio
    
    Android Studio is an IDE for building Android apps.
    
    <!-- related-key-terms: IDE, Android SDK, Kotlin -->

4. Install dependencies

If not already installed:

npm install

5. Generate the SCORM ZIP

Run:

npm run blackboard

The generated SCORM package will appear in:

./interactive-codelab/scorm/

6. Upload to your LMS

Upload the generated .zip file into your LMS (e.g. Blackboard) as a SCORM package.


Writing a Supported Markdown File

Module Title (Required)

The first major heading (#) defines the module name.

# Exercise 1: My Android CV

Rules:

  • The first level-1 heading (#) is used as the SCORM module title
  • A second level-1 heading (#) is optional and enables Bonus Tasks (see below)
  • Avoid additional # headings after the bonus heading, as only the first two are used for structure

Cover Page Content

Anything after the first major heading and before the first subheading (##) becomes the cover page.

Example:

# Exercise 1: My Android CV

Welcome to Week 1 of Android development.
In this module, you will build a simple CV app using Kotlin.

This content is shown to the learner before the module starts.

Image of Cover Page example

Banner Image

You can set a banner image for the module by adding an image immediately after the main heading with the description exactly:

![Banner Image](assets/banner.png)

Notes:

  • The description must be Banner Image
  • The image must exist in public/assets/
  • The banner image is optional and will only be displayed if there is content on the cover page.

Revealable Hints and Solutions

Use :::hint and :::solution directive blocks anywhere inside a step to add help that is hidden until the learner chooses to reveal it. This is useful for gradually offering support without immediately showing the complete answer.

:::hint
Look at which exception is thrown by `int.Parse`.
:::

:::solution
Use `int.TryParse` when invalid user input is an expected possibility.
:::

Rules:

  • Each hint or solution becomes its own revealable panel with a button.
  • The content inside the block supports normal Markdown, including inline code, lists, links, and fenced code blocks.
  • Put hints before solutions when you want learners to request small pieces of help before revealing the full answer.

File Tab Blocks

Use :::tabs when a step needs to show several related files without cluttering the page with multiple separate code blocks. Each file starts with ---tab followed by the label to display on the tab. The content inside each tab supports normal Markdown, so fenced code blocks still get syntax highlighting and copy buttons.

:::tabs
---tab Program.cs
```csharp
Console.WriteLine("Hello from the main program");
```

---tab CustomerService.cs
```csharp
public class CustomerService
{
    public string GetDisplayName() => "Ada Lovelace";
}
```

---tab CustomerServiceTests.cs
```csharp
[Fact]
public void GetDisplayName_returns_name()
{
    Assert.Equal("Ada Lovelace", new CustomerService().GetDisplayName());
}
```
:::

Rules:

  • Start the group with :::tabs and end it with :::.
  • Start each tab with ---tab FileName.ext.
  • Put each file's code or Markdown content below its ---tab line.
  • Use tabs only when files are related. Normal fenced code blocks that are not inside a tab block continue to render as standard code blocks.

Steps and Navigation

Each module step is defined by a level-2 heading (##):

## Create the Project

Rules:

  • Each ## heading becomes a separate step
  • Headings deeper than this (e.g. ###) do not create new steps
  • Use ### and deeper headings only for structure within a step
  • Avoid adding in text that indicates what step it is (e.g. "Step 1: "). The tool will automatically number each sub-heading as a step when compiled.
Example of steps generated

Suggested Time to Complete a Step

You can optionally show a suggested completion time beside the step heading in the generated module. Add the suggested time marker immediately underneath the relevant ## heading using this exact format:

## Create the Project
<!-- suggested-time: 20 minutes -->

Step content starts here.

Rules:

  • The marker must be the first line directly below the ## heading.
  • The marker must use the exact syntax <!-- suggested-time: your time text -->.
  • Replace your time text with the text you want displayed, such as 10 minutes, 1 hour, or 15–20 minutes.
  • If the marker is missing, placed elsewhere, or does not match the exact format, no suggested time is shown for that step.
  • The marker is removed from the learner-facing content and displayed as a coloured pill to the right of the step heading.
  • Other <!-- --> comments outside fenced code blocks are also hidden from learner-facing content.

Inline Quiz Blocks

You can place a quiz anywhere in the module content (overview, main steps, or bonus steps) using:

:::quiz
This is a question?
- [] Answer 1
- [x] This answer is correct
- [] Answer 3
- [] Answer 4
:::

Rules:

  • Start with :::quiz and end with :::.
  • All lines before the first bullet are treated as the quiz question.
  • Options must use bullet points with checkbox syntax:
    • - [] for an incorrect option
    • - [x] for the correct option
  • At least one - [x] option must be present.

Learner behavior:

  • Selecting an option marks the quiz immediately.
  • Correct answers are highlighted with a green tick.
  • If the learner chooses incorrectly, their selected option is marked red, the correct answer is marked green, and all other options are greyed out.
  • A Retry button appears for incorrect attempts so the learner can reset and try again.

SCORM tracking behavior:

  • Quiz selections are saved in SCORM suspend data.
  • Re-opening the module restores previously selected quiz answers.
  • Choosing Restart from beginning clears quiz attempts along with other progress.

Bonus Tasks (Optional)

You can define optional bonus tasks by adding a second major heading (#) in module.md.

How it works:

  • The second # heading text becomes the Bonus section title in the left sidebar.
  • Any following ## headings after that second # become bonus task steps.
  • Bonus tasks are separate from main module progress and have their own progress indicator.

Example:

# Exercise 1: My Android CV

Welcome text for the module...

## Main step one
Main content...

## Main step two
Main content...

# Bonus Tasks

## Add an extra layout variant
Bonus content...

## Add accessibility labels
Bonus content...

Behavior notes:

  • If no second # heading is present, no bonus section is shown.
  • Bonus tasks are unlocked from the final main step via the Bonus tasks button.
  • On smaller screens, only the active track's radial progress is shown (main or bonus).

Images

Images are supported using standard Markdown syntax:

![Description](assets/image-name.png)

Important rules:

  • Images must be stored in ./interactive-codelab/public/assets/
  • Always link using relative paths starting with assets/
  • Do not use /assets/... (this will point to the LMS root and break)

Correct:

![App Screenshot](assets/app.png)

Incorrect:

![App Screenshot](/assets/app.png)
Example of image in module

Code Blocks

Code blocks are fully supported. These will be formatted using Highlight.js automatically.

Use triple backticks and specify a language where possible so formatting is correct:

```kotlin
fun main() {
    println("Hello World")
}
```

Light mode example: Light mode code block

Dark mode example: Dark mode code block

Inline code is also supported using backticks. Inline code will not receive automatic formatting like code blocks:

`val name = "Joshua"`

Callouts (Notes, Warnings, etc.)

The tool supports GitHub-style callouts such as Note, Warning, Important, and others.

Example:

> [!NOTE]
> This is an example.

... will produce the following:

Note

This is an example.

Callout example for Note

Supported formats are based on GitHub’s callout syntax:
https://github.com/orgs/community/discussions/16925


Text Formatting

Standard GitHub Markdown is supported, including:

  • Bold
  • Italics
  • Inline code
  • Bullet lists
  • Numbered lists

Example:

- Kotlin
- Android Studio
- RecyclerView
1. Create the project
2. Add resources
3. Run the app

Hyperlinks

Standard Markdown links are supported:

[Android Developer Docs](https://developer.android.com)

All links will automatically open in a new tab when clicked in the LMS.


Dynamic Name Substitution

The following placeholders will be replaced automatically with the learner’s name, with all special characters and spaces removed (as provided by the LMS):

[name]
[yourname]

Example:

Place the contents of your application into a folder called [name].

Notes:

  • The substituted name contains no spaces or special characters and are converted to lowercase

SCORM Configuration (Optional)

You can configure SCORM metadata using HTML comments at the very top of the Markdown file.

SCORM Description

Sets the description shown in the LMS when importing the module.

<!-- scorm:description Build a simple CV app in Android Studio. You’ll add an image, style text, and learn string resources. -->

Course Code

Replaces the default “Developer Module” label in the SCORM UI.

<!-- scorm:courseCode BIT608 Mobile Application Development -->

Example with both:

<!-- scorm:description Build a simple CV app in Android Studio. You’ll add an image, style text, and learn string resources. -->
<!-- scorm:courseCode BIT608 Mobile Application Development -->

# Exercise 1: My Android CV

Both fields are optional and will be replaced by defaults if not specified.


Summary of Key Rules

  • One # heading only (module title)
  • Use ## for steps
  • Assets must live in public/assets/
  • Link images using assets/filename.png
  • Rename the Markdown file to module.md
  • Clean assets and content directories before each build
  • Use HTML comments for SCORM metadata
  • The second # indicates bonus tasks, with subsequent ## representing bonus steps

Optional concept guides

Place an optional guides.md beside module.md and keywords.md in content/ to add deeper walkthroughs. Each guide begins with a level-one heading whose text must match a keyword heading (case-insensitively). Only matched keywords display See it in action; unmatched guides are ignored with a development warning. Guide bodies support normal Markdown, including code, images, links, lists, tables, and callouts. Level-two (##) headings remain ordinary sections within a guide and never create lesson steps.

# Activity

## Start with the idea

An Activity provides a screen where a learner interacts with an Android app.

The file is optional, and guides do not create completion items or affect SCORM progress. Exercise build workflows must copy guides.md into content/ whenever guide support is required.

About

A Node-based tool for generating SCORM-compatible interactive learning modules from a single Markdown (.md) file. Designed for code-labs for use in Schools and Universities for scaffolding concepts.

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages