Skip to content

Configuration

You can configure the appearance and behavior of a TutorialKit lesson by setting up properties in the lesson’s frontmatter block.

Note on inheritance

Some options, like “title,” will naturally be unique for each lesson. For others, like “template,” the value might be the same across multiple lessons, chapters, or even an entire tutorial. That’s why we’ve made it possible to set some properties on a chapter, part, or tutorial level. We call these values inherited.

For instance, if you set template: "simple" for a given part, all chapters and lessons in this part will use the “simple” template.

It’s also possible to override inherited properties on a lower level. For example, if you set template: "simple" for a part, but template: "advanced" for a lesson, that specific lesson will use the “advanced” template.

Configuration location

  • In case of a lesson, set the configuration in the frontmatter of the content.md file.
  • For a chapter, part or the whole tutorial, set the configuration in the frontmatter of the meta.md file on the respective level.

Options reference

type

Defines the type of the metadata.

Required Values Inherited
yes 'part', 'chapter' or 'lesson' no
title

The title of the part, chapter, or lesson.

Required Type Inherited
yes string no
slug

Lets you customize the URL segment which is /:partSlug/:chapterSlug/:lessonSlug

Required Type Inherited
no string no
i18n

Lets you define alternative texts used in the UI. This is useful for localization.

Required Type Inherited
no I18nText yes

The I18nText type has the following shape:

type I18nText = {
/**
* Template on how to format a part. Variables: ${index} and ${title}.
*
* @default 'Part ${index}: ${title}'
*/
partTemplate?: string,
/**
* Text of the edit page link.
*
* @default 'Edit this page'
*/
editPageText?: string,
/**
* Text of the WebContainer link.
*
* @default 'Powered by WebContainers'
*/
webcontainerLinkText?: string,
/**
* Text shown on the call to action button to start webcontainer when boot was blocked
* due to memory restrictions.
*
* @default 'Start WebContainer'
*/
startWebContainerText?: string,
/**
* Text shown in the preview section when there are no steps to run and no preview to show.
*
* @default 'No preview to run nor steps to show'
*/
noPreviewNorStepsText?: string,
/**
* Text shown on top of the file tree.
*
* @default 'Files'
*/
filesTitleText?: string,
/**
* Text shown on file tree's context menu's file creation button.
*
* @default 'Create file'
*/
fileTreeCreateFileText?: string,
/**
* Text shown on file tree's context menu's folder creation button.
*
* @default 'Create folder'
*/
fileTreeCreateFolderText?: string,
/**
* Text shown on dialog when user attempts to edit files that don't match allowed patterns.
*
* @default 'This action is not allowed'
*/
fileTreeActionNotAllowedText?: string,
/**
* Text shown on dialog when user attempts create file or folder that already exists on filesystem but is not visible on file tree, e.g. template files.
*
* @default 'File exists on filesystem already'
*/
fileTreeFileExistsAlreadyText?: string,
/**
* Text shown on dialog describing allowed patterns when file or folder creation failed.
*
* @default 'Created files and folders must match following patterns:'
*/
fileTreeAllowedPatternsText?: string,
/**
* Text shown on confirmation buttons on dialogs.
*
* @default 'OK'
*/
confirmationText?: string,
/**
* Text shown on top of the steps section.
*
* @default 'Preparing Environment'
*/
prepareEnvironmentTitleText?: string,
/**
* Text shown on top of the preview section when `previews[_].title` is not configured.
*
* @default 'Preview'
*/
defaultPreviewTitleText?: string,
/**
* Title attribute for the preview reload button.
*
* @default 'Reload Preview'
*/
reloadPreviewTitle?: string,
/**
* Text for the toggle terminal button.
*
* @default 'Toggle Terminal'
*/
toggleTerminalButtonText?: string,
/**
* Text for the solve button.
*
* @default 'Solve'
*/
solveButtonText?: string,
/**
* Text for the reset button.
*
* @default 'Reset'
*/
resetButtonText?: string,
}
focus

Defines which file should be opened in the code editor by default when lesson loads.

Required Type Inherited
no string yes
editor

Configures options for the editor and its file tree. Editor can be hidden by providing false. Optionally you can hide just file tree by providing fileTree: false.

File tree can be set to allow file editing from right clicks by setting fileTree.allowEdits: true.

Required Type Inherited
no Editor yes

The Editor type has the following shape:

type GlobPattern = string
type Editor =
| false
| { editor: { allowEdits: boolean | GlobPattern | GlobPattern[] } }

Example values:

editor: false # Editor is hidden
editor: # Editor is visible
fileTree: false # File tree is hidden
editor: # Editor is visible
fileTree: # File tree is visible
allowEdits: true # User can add new files and folders from the file tree
editor: # Editor is visible
fileTree: # File tree is visible
allowEdits: "/src/**" # User can add files and folders anywhere inside "/src/"
editor: # Editor is visible
fileTree: # File tree is visible
allowEdits:
- "/*" # User can add files and folders directly in the root
- "/first-level/allowed-filename-only.js" # Only "allowed-filename-only.js" inside "/first-level" folder
- "**/second-level/**" # Anything inside "second-level" folders anywhere
previews

Configure which ports should be used for the previews allowing you to align the behavior with your demo application’s dev server setup. If not specified, the lowest port will be used. Optionally you can hide the preview by providing previews: false.

Required Type Inherited
no Preview[] | false yes

The Preview type has the following shape:

type Preview =
| number
| string
| [port: number, title: string]
| [port: number, title: string, pathname: string]
| { port: number, title: string, pathname?: string }

Example value:

previews:
- 3000 # Preview is on :3000/
- "3001/docs" # Preview is on :3001/docs/
- [3002, "Dev Server"] # Preview is on :3002/. Displayed title is "Dev Server".
- [3003, "Dev Server", "/docs"] # Preview is on :3003/docs/. Displayed title is "Dev Server".
- { port: 3004, title: "Dev Server" } # Preview is on :3004/. Displayed title is "Dev Server".
- { port: 3005, title: "Dev Server", pathname: "/docs" } # Preview is on :3005/docs/. Displayed title is "Dev Server".
previews: false # Do not show preview panel
mainCommand

The main command to be executed. This command will run after the prepareCommands.

Required Type Inherited
no Command yes

The Command type has the following shape:

type Command = string
| [command: string, title: string]
| { command: string, title: string }
prepareCommands

List of commands to execute sequentially. They are typically used to install dependencies or to run scripts.

Required Type Inherited
no Command[] yes

The Command type has the following shape:

type Command = string
| [command: string, title: string]
| { command: string, title: string }
filesystem

Configures how changes such as files being modified or added in WebContainer should be reflected in the editor when they weren’t caused by the user directly. By default, the editor will not reflect these changes.

An example use case is when a user runs a command that modifies a file. For instance when a package.json is modified by doing an npm install <xyz>. If watch is set to true, the file will be updated in the editor. If set to false, the file will not be updated.

This property is by default set to false as it can impact performance. If you are creating a lesson where the user is expected to modify files outside the editor, you may want to keep this to false.

If you would like files to be added or removed from the editor automatically, you need to specify an array of globs that will determine which folders and files to watch for changes.

Required Type Inherited
no FileSystem yes

The FileSystem type has the following shape:

type FileSystem = {
watch: boolean | string[]
}

Example values:

filesystem:
watch: true # Filesystem changes to files already in the editor are reflected in the editor
filesystem:
watch: false # Or if it's omitted, the default value is false
filesystem:
watch: ['/*.json', '/src/**/*'] # Files changed, added or deleted that match one of the globs are updated in the editor
terminal

Configures one or more terminals. TutorialKit provides two types of terminals: read-only, called output, and interactive, called terminal. Note, that there can be only one output terminal.

You can define which terminal panel will be active by default by specifying the activePanel value. The value is the given terminal’s position in the panels array. If you omit the activePanel property, the first panel will be the active one.

You can set terminal open by default by specifying the open value.

An interactive terminal will disable the output redirect syntax by default. For instance, you cannot create a file world.txt with the contents hello using the command echo hello > world.txt. The reason is that this could disrupt the lesson if a user overwrites certain files. To allow output redirection, you can change the behavior with the allowRedirects setting. You can define this setting either per panel or for all panels at once.

Additionally, you may not want users to run arbitrary commands. For example, if you are creating a lesson about vitest, you could specify that the only command the user can run is vitest by providing a list of allowCommands. Any other command executed by the user will be blocked. You can define the allowCommands setting either per panel or for all panels at once.

By default, in every new lesson terminals start a new session. If you want to keep the terminal session between lessons, you can specify the id property for a given terminal panel and keep the same id across lessons.

Required Type Inherited
no Terminal yes

The Terminal type has the following shape:

type Terminal = {
panels: TerminalPanel[],
activePanel?: number,
allowRedirects?: boolean,
allowCommands?: string[],
open?: boolean,
}
type TerminalPanel = TerminalType
| [type: TerminalType, title: string]
| { type: TerminalType, title?: string, id?: string, allowRedirects?: boolean, allowCommands?: boolean }
type TerminalType = 'terminal' | 'output'

Example value:

terminal:
open: true
activePanel: 1
panels:
- ['output', 'Dev Server']
- type: terminal
id: 'cmds'
title: 'Command Line'
allowRedirects: true
allowCommands:
- ls
- echo
autoReload

Navigating to a lesson that specifies autoReload will always reload the preview. This is typically only needed if your server does not support HMR.

Required Type Inherited
no boolean yes
template

Specifies which folder from the src/templates/ directory should be used as the basis for the code. See the “Code templates” guide for a detailed explainer.

Required Type Inherited
no string yes

Display a link in lesson for editing the page content. The value is a URL pattern where ${path} is replaced with the lesson’s location relative to the src/content/tutorial.

Required Type Inherited
no string|false yes
editPageLink: https://github.com/stackblitz/tutorialkit/blob/main/packages/template/src/content/tutorial/${path}

The inherited value can be disabled in specific parts using false.

editPageLink: false
openInStackBlitz

Display a link for opening current lesson in StackBlitz.

Required Type Inherited
no OpenInStackBlitz yes

The OpenInStackBlitz type has the following shape:

type OpenInStackBlitz =
| boolean
| { projectTitle?: string, projectDescription?: string, projectTemplate?: TemplateType }
type TemplateType = "html" | "node" | "angular-cli" | "create-react-app" | "javascript" | "polymer" | "typescript" | "vue"

downloadAsZip

Display a button for downloading the current lesson as .zip file. Defaults to false. The default filename is constructed by concatenating folder names of part, chapter and lesson.

Required Type Inherited
no DownloadAsZip yes

The DownloadAsZip type has the following shape:

type DownloadAsZip =
| boolean
| { filename?: string }
meta

Configures <meta> tags for Open Graph protocole and Twitter. TutorialKit will use your logo as the default image.

Required Type Inherited
no MetaTagsSchema yes

The MetaTagsSchema type has the following shape:

type MetaTagsSchema = {
image?: string;
description?: string;
title?: string;
}

Example value:

meta:
image: /cover.png
title: Title shown on social media and search engines
description: Description shown on social media and search engines
custom

Assign custom fields to a chapter/part/lesson.

Required Type Inherited
no Record<string,any> yes

This is useful when you want to consume items for the default tutorial collection in order to implement custom features.

custom:
publishedAt: 2024-16-10
tags: tutorialkit,astro,vite
import { getCollection } from 'astro:content';
const collection = await getCollection('tutorial');
for (const entry of collection) {
console.log("This part was published at:", entry.data?.custom?.publishedAt)
}

Configure the Tutorialkit Astro integration

@tutorialkit/astro is an integration for Astro. You can configure the integration in your astro.config.ts file.

astro.config.ts
import tutorialkit from "@tutorialkit/astro";
import { defineConfig } from "astro/config";
export default defineConfig({
devToolbar: {
enabled: false,
},
integrations: [
tutorialkit(),
],
});

You can pass the following options to the tutorialkit integration:

components

type: OverrideComponentsOptions

Provide the path to the components you want to override.

tutorialkit({
components: {
TopBar: './src/components/CustomTopBar.astro',
},
});

See Overriding Components for details of all the components that you can override.

defaultRoutes

type: boolean | "tutorial-only"
default: true

Controls whether the tutorial routes are automatically added to your project. When set to true, it additionally adds a redirect from / to the first tutorial. Use "tutorial-only" to only add the tutorial routes without the redirect.