TutorialKit’s API can be used in custom components to provide highly custom experience in the tutorials.
Below are listed few examples to solve real-world use cases. See TutorialKit API for API documentation.
Access tutorial state
In this example we’ll read contents of index.js
using Tutorial Store APIs.
When user clicks Help
button, we check the contents of index.js
and provide them hints about next steps.
import tutorialStore from " tutorialkit:store " ;
import { Dialog } from " @tutorialkit/react " ;
import { useState } from " react " ;
import { parseModule } from " magicast " ;
export default function HelpButton () {
const [ message , setMessage ] = useState < string | null > ( null );
const files = tutorialStore . documents . value ;
const index = files[ " /index.js " ] . value as string ;
const message = verifyIndexJs (index);
< button onClick = { onClick } className = " px-4 py-1 rounded-md bg-tk-elements-primaryButton-backgroundColor text-tk-elements-primaryButton-textColor " >
< Dialog title = " Help " confirmText = " OK " onClose = { () => setMessage ( null ) } >
function verifyIndexJs ( code : string ) {
const mod = parseModule (code);
mod . $ast . type === " Program " &&
( node ) => node . type === " FunctionDeclaration " && node . id . name === " sum "
return " Your index.js should have a sum function " ;
if (mod . exports . default ?. $name !== " sum " ) {
return " Your index.js should export sum as default export " ;
title : TutorialKit API usage example
import HelpButton from ' @components/HelpButton ' ;
# TutorialKit API usage example
Click this button if you get stuck:
< HelpButton client : load />
Write to terminal
In this example we’ll write commands to the terminal using Tutorial Store APIs.
When user clicks Run tests
button, we run npm run test
command into the terminal.
This command starts our test
command defined in template’s package.json
.
import tutorialStore from ' tutorialkit:store ' ;
export default function TerminalWriter () {
async function onClick () {
const terminal = tutorialStore . terminalConfig . value !. panels [ 0 ];
terminal . input ( ' npm run test \n ' );
className = " px-4 py-1 my-3 cursor-pointer border-1 border-tk-border-primary rounded-md bg-tk-elements-primaryButton-backgroundColor text-tk-elements-primaryButton-textColor "
title : Write to Terminal example
import TerminalWriter from " @components/TerminalWriter " ;
# Write to Terminal example
Fix < code > counter.js </ code > and run the tests!
< TerminalWriter client : load />
Provide feedback to user when lesson is solved
In this example we’ll use the Tutorial Core APIs to congratulate user when they solve the lesson code.
Every time user edits the math.js
, we run node check-lesson.js
in the webcontainer and see if the process exits with non-erroneous exit code.
Once the exit code indicates success, we inform user with message.
import { Dialog } from ' @tutorialkit/react ' ;
import { useEffect, useState } from ' react ' ;
import { webcontainer } from ' tutorialkit:core ' ;
import tutorialStore from ' tutorialkit:store ' ;
export default function LessonChecker () {
const [ success , setSuccess ] = useState ( false );
let timeout : ReturnType < typeof setTimeout > | undefined = undefined ;
const unsubscribe = tutorialStore . onDocumentChanged ( ' /math.js ' , () => {
timeout = setTimeout ( async () => {
if ( await checkLesson ()) {
return function cleanup () {
< Dialog title = " Lesson complete " confirmText = " OK " onClose = { () => setSuccess ( false ) } >
Lesson complete, congratulations! 🎉
async function checkLesson () : Promise < boolean > {
const webcontainerInstance = await webcontainer;
const process = await webcontainerInstance . spawn ( ' node ' , [ ' ./check-lesson.mjs ' ]);
const exitCode = await process . exit ;
import * as math from ' ./math.js ' ;
if ( math . sum ( 25 , 32 ) !== 57 ) {
if ( math . multiply ( 3 , 25 ) !== 75 ) {
title : TutorialKit API usage example
import LessonChecker from ' @components/LessonChecker ' ;
# TutorialKit API usage example
Solve < code > math.js </ code > and you'll see notification about completed lesson!
< LessonChecker client : load />