scaffold_feature
Scaffold a complete feature integration for mobile-web APIs, generating hook, component, and types files with integration instructions.
Instructions
Scaffold complete feature integration including hook, component, and types. Returns multiple files with integration instructions.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| feature | Yes | The SDK feature to scaffold | |
| directory | No | Target directory path for file suggestions | |
| includeTests | No | Include test file scaffolding (default: true) |
Implementation Reference
- src/tools/index.ts:83-106 (registration)Tool registration with name 'scaffold_feature', description, and inputSchema (feature, directory, includeTests). feature is required and must be one of SDK_FEATURES.
{ name: "scaffold_feature", description: "Scaffold complete feature integration including hook, component, and types. Returns multiple files with integration instructions.", inputSchema: { type: "object", properties: { feature: { type: "string", enum: SDK_FEATURES, description: "The SDK feature to scaffold", }, directory: { type: "string", description: "Target directory path for file suggestions", }, includeTests: { type: "boolean", description: "Include test file scaffolding (default: true)", }, }, required: ["feature"], }, }, - src/tools/scaffold-feature.ts:23-100 (handler)Main scaffoldFeature handler function. Validates the feature, generates scaffold files (types, hook, component, optional tests), and returns a markdown-formatted response with file contents and integration instructions.
export async function scaffoldFeature( args: Record<string, unknown> ): Promise<{ content: Array<{ type: "text"; text: string }> }> { const { feature, directory = "src", includeTests = true, } = args as unknown as ScaffoldFeatureArgs; if (!feature || !featureDescriptions[feature]) { return { content: [ { type: "text", text: `Invalid feature. Available features:\n${Object.entries(featureDescriptions) .map(([key, desc]) => `- ${key}: ${desc}`) .join("\n")}`, }, ], }; } const capitalizedFeature = feature.charAt(0).toUpperCase() + feature.slice(1); const hookName = `use${capitalizedFeature}`; const componentName = `${capitalizedFeature}Component`; const requiresPermission = permissionFeatures.includes(feature as typeof permissionFeatures[number]); const files = generateScaffoldFiles(feature, capitalizedFeature, hookName, componentName, directory, includeTests, requiresPermission); return { content: [ { type: "text", text: `# ${capitalizedFeature} Feature Scaffold ${featureDescriptions[feature]} ## Files to Create ${files.map((f) => `### ${f.path}\n\`\`\`${f.language}\n${f.content}\n\`\`\``).join("\n\n")} ## Integration Steps 1. **Install the SDK** (if not already installed): \`\`\`bash npm install @appolabs/appo # or pnpm add @appolabs/appo \`\`\` 2. **Create the files** listed above in your project 3. **Import and use** in your app: \`\`\`tsx import { ${componentName} } from './${directory}/components/${feature}'; function App() { return <${componentName} />; } \`\`\` ${requiresPermission ? `## Permission Handling This feature requires user permission. The scaffold includes: - Permission request on first interaction - Graceful handling of denied permissions - Loading states during permission checks **Important:** Always explain to users WHY you need this permission before requesting it.` : ""} ## Native vs Web Behavior The SDK provides automatic fallbacks for web browsers: ${getNativeFallbackInfo(feature)}`, }, ], }; } - src/tools/scaffold-feature.ts:3-7 (schema)TypeScript interface ScaffoldFeatureArgs defining input: feature (SdkFeature), directory (optional string), includeTests (optional boolean).
interface ScaffoldFeatureArgs { feature: SdkFeature; directory?: string; includeTests?: boolean; } - Helper function getNativeFallbackInfo returning web fallback descriptions per feature.
function getNativeFallbackInfo(feature: SdkFeature): string { const fallbacks: Record<SdkFeature, string> = { push: "- Web: Returns 'denied' permission, null token", biometrics: "- Web: Returns false for availability", camera: "- Web: Returns 'denied' permission", location: "- Web: Returns 'denied' permission (consider using browser Geolocation API)", haptics: "- Web: Silent no-op (no vibration API used)", storage: "- Web: Falls back to localStorage", share: "- Web: Uses navigator.share() if available, otherwise fails gracefully", network: "- Web: Uses navigator.onLine and online/offline events", device: "- Web: Parses user agent for basic device info", }; return fallbacks[feature]; } - Helper function generateScaffoldFiles that creates the list of files (types, hook, component, optional test). Delegates to specific generators.
function generateScaffoldFiles( feature: SdkFeature, _capitalizedFeature: string, hookName: string, componentName: string, directory: string, includeTests: boolean, _requiresPermission: boolean ): Array<{ path: string; language: string; content: string }> { const files: Array<{ path: string; language: string; content: string }> = []; // Types file files.push({ path: `${directory}/types/${feature}.ts`, language: "typescript", content: generateTypesFile(feature), }); // Hook file files.push({ path: `${directory}/hooks/${hookName}.ts`, language: "typescript", content: generateHookFile(feature, hookName, _requiresPermission), }); // Component file files.push({ path: `${directory}/components/${componentName}.tsx`, language: "tsx", content: generateComponentFile(feature, componentName, hookName), }); // Test file if (includeTests) { files.push({ path: `${directory}/__tests__/${hookName}.test.ts`, language: "typescript", content: generateTestFile(feature, hookName), }); } return files; }