Skip to content

Commit ddcdc3a

Browse files
committed
docs: add example of tutorialkit:core usage
1 parent b05fc55 commit ddcdc3a

File tree

2 files changed

+87
-2
lines changed

2 files changed

+87
-2
lines changed
Binary file not shown.

docs/tutorialkit.dev/src/content/docs/guides/using-low-level-apis.mdx

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Using low level APIs
33
---
4-
4+
import taskListVideo from "./images/tk-task-list.webm";
55
import { HelpButton } from "@components/react-examples/HelpButton";
66
import '@tutorialkit/astro/default-theme.css';
77

@@ -57,7 +57,7 @@ import { useState } from "react";
5757
export function HelpButton() {
5858
const [message, setMessage] = useState<string | null>(null);
5959

60-
async function onClick() {
60+
function onClick() {
6161
const files = tutorialStore.documents.value;
6262
const index = files["/index.js"].value as string;
6363

@@ -102,3 +102,88 @@ import { HelpButton } from "@/components/HelpButton";
102102
In this lesson we'll learn about...
103103
Click this button if you need help: <HelpButton client:load />
104104
```
105+
106+
## Tutorial Core
107+
108+
You can access Tutorial Core by importing the `tutorialkit:core` entrypoint.
109+
110+
```ts
111+
import * as core from "tutorialkit:core";
112+
```
113+
114+
The Tutorial Core provides access to webcontainer APIs. You can use it for example to read and modify files on the virtual file system.
115+
116+
```ts
117+
import * as core from "tutorialkit:core";
118+
119+
const webcontainer = await core.webcontainer;
120+
const contents = await webcontainer.fs.readdir("/", "utf8");
121+
122+
console.log(contents);
123+
[
124+
"index.html",
125+
"node_modules",
126+
"package-lock.json",
127+
"package.json",
128+
"vite.config.ts"
129+
]
130+
```
131+
132+
### Example usage in React component
133+
134+
Here is an example of custom React component that looks for updates in `/index.js` and provides user information about their lesson status.
135+
136+
<video src={taskListVideo} controls />
137+
138+
```tsx title="src/components/TaskList.tsx"
139+
import * as core from "tutorialkit:core";
140+
import { useEffect, useState } from "react";
141+
142+
export function TaskList() {
143+
const [hasDefaultExport, setDefaultExport] = useState<boolean>(false);
144+
const [hasSumFunction, setSumFunction] = useState<boolean>(false);
145+
146+
useEffect(() => {
147+
const unsubscribe = subscribeFileChanges("/index.js", (content) => {
148+
// Naive text based checking just for example. Use proper AST analysis in real lessons.
149+
setDefaultExport(content.includes("export default"));
150+
setSumFunction(content.includes("function sum"));
151+
});
152+
153+
return () => unsubscribe();
154+
}, []);
155+
156+
return (
157+
<ol>
158+
<li>Add default export to index.js {hasDefaultExport ? "" : ""}</li>
159+
<li>Add <code>function sum</code> to index.js {hasSumFunction ? "" : ""}</li>
160+
</ol>
161+
);
162+
}
163+
164+
function subscribeFileChanges(filename: string, callback: (content: string) => void) {
165+
const controller = new AbortController();
166+
167+
core.webcontainer.then((webcontainer) => {
168+
const watcher = webcontainer.fs.watch(filename, async () => {
169+
const content = await webcontainer.fs.readFile(filename, "utf8");
170+
callback(content);
171+
});
172+
173+
controller.signal.addEventListener("abort", () => watcher.close());
174+
});
175+
176+
return () => controller.abort();
177+
}
178+
```
179+
180+
```mdx title="content.mdx"
181+
---
182+
type: lesson
183+
title: Lesson Topic
184+
---
185+
186+
import { TaskList } from "@/components/TaskList";
187+
188+
<TaskList client:load />
189+
```

0 commit comments

Comments
 (0)