Skip to content

Commit 7ff8038

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

File tree

2 files changed

+89
-2
lines changed

2 files changed

+89
-2
lines changed
Binary file not shown.

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

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

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

60-
async function onClick() {
61+
function onClick() {
6162
const files = tutorialStore.documents.value;
6263
const index = files["/index.js"].value as string;
6364

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

0 commit comments

Comments
 (0)