handbook-introduction
Understand the HTML-over-the-wire approach with Turbo. Learn how Turbo Drive, Frames, Streams, and Native combine to build fast web applications without heavy JavaScript frameworks.
Instructions
Introduction to Turbo - learn about HTML-over-the-wire approach, persistent processes, and how Turbo Drive, Frames, Streams, and Native work together to create fast web applications without heavy JavaScript frameworks
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/index.ts:21-43 (handler)The core handler logic for the 'handbook-introduction' tool (shared across all doc tools). Reads the markdown content using readMarkdownFile and formats it as MCP response content, with error handling.async () => { try { const content = await readMarkdownFile(path.join(folder, file)); return { content: [ { type: "text", text: content } ] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Error reading ${file}: ${errorMessage}` } ] }; } }
- src/index.ts:17-45 (registration)Dynamic registration of the 'handbook-introduction' tool (and others) on the MCP server using config from docFiles.docFiles.forEach(({ folder, file, name, description }) => { server.tool( name, description, async () => { try { const content = await readMarkdownFile(path.join(folder, file)); return { content: [ { type: "text", text: content } ] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Error reading ${file}: ${errorMessage}` } ] }; } } ); });
- src/config.ts:14-19 (schema)Configuration schema entry specific to the 'handbook-introduction' tool, mapping name to file path and description.{ folder: 'handbook', file: '01_introduction.md', name: 'handbook-introduction', description: 'Introduction to Turbo - learn about HTML-over-the-wire approach, persistent processes, and how Turbo Drive, Frames, Streams, and Native work together to create fast web applications without heavy JavaScript frameworks' },
- src/documentReader.ts:14-61 (helper)Key helper function called by the handler to fetch and cache the markdown file content from GitHub or local fallback.export async function readMarkdownFile(filename: string): Promise<string> { const filePath = path.join(docsFolder, filename); if (!filePath.startsWith(docsFolder)) { throw new Error("Invalid file path"); } // Get current commit info if we don't have it yet if (!mainBranchInfo) { try { const commitInfo = await fetchMainBranchInformation(); const cacheKey = `${commitInfo.sha.substring(0, 7)}-${commitInfo.timestamp}`; mainBranchInfo = { ...commitInfo, cacheKey }; } catch (shaError) { console.error('Failed to get GitHub commit info, falling back to direct fetch'); } } // Try to read from cache first if we have commit info if (mainBranchInfo) { const cachedFilePath = path.join(cacheFolder, mainBranchInfo.cacheKey, filename); try { const content = await fs.promises.readFile(cachedFilePath, "utf-8"); console.error(`Using cached content for ${mainBranchInfo.cacheKey}: ${filename}`); return content; } catch (cacheError) { // Cache miss, continue to fetch from GitHub } } // Fetch from GitHub try { return await fetchFromGitHub(filename, mainBranchInfo?.cacheKey); } catch (githubError) { console.error(`GitHub fetch failed: ${githubError}, attempting to read from local files...`); // Fallback: read from local files try { return await fs.promises.readFile(filePath, "utf-8"); } catch (localError) { const githubErrorMessage = githubError instanceof Error ? githubError.message : String(githubError); const localErrorMessage = localError instanceof Error ? localError.message : String(localError); throw new Error(`Failed to read file from GitHub (${githubErrorMessage}) and locally (${localErrorMessage})`); } } }
- src/config.ts:4-9 (schema)TypeScript interface defining the schema for each tool's configuration object.export interface DocFile { folder: string; file: string; name: string; description: string; }