Automatically generate beautiful, interactive documentation for your vals by parsing TypeScript AST and extracting functions, classes, interfaces, types, and constants with their JSDoc comments.
- 📝 Automatic Code Parsing - Extracts functions, classes, interfaces, type aliases, and constants
- 💬 JSDoc Support - Parses
@param,@returns,@example, and@deprecatedtags - 🔍 Search & Filter - Quickly find what you're looking for
- ⚡ Fast Caching - Sub-second responses for cached documentation (1-hour TTL)
- 🎨 Clean UI - Responsive design with Tailwind CSS via Twind
- 🚀 Serverless - Runs on Val Town's serverless platform
Generate documentation JSON for any public val:
GET /api/docs?val=username/valname
Query Parameters:
val(required) - Val identifier in formatusername/valnamerefresh(optional) - Set totrueto bypass cache
Example:
curl "https://docs-gen.val.run/api/docs?val=stevekrouse/example"
Response:
{ "val": "stevekrouse/example", "version": "1", "generatedAt": "2025-11-17T12:00:00.000Z", "exports": { "functions": [...], "classes": [...], "interfaces": [...], "types": [...], "constants": [...] }, "imports": [...], "metadata": {...} }
Visit the root URL with a val query parameter to view interactive documentation:
https://docs-gen.val.run/?val=username/valname
The UI provides:
- Searchable sidebar navigation
- Syntax-highlighted code examples
- Detailed parameter and return type information
- JSDoc comment rendering
- Direct links to source code locations
.
├── backend/
│ ├── docGenerator.http.ts # Main HTTP entry point
│ ├── routes/
│ │ ├── apiDocs.ts # API route handler
│ │ └── ui.ts # UI route handler
│ └── services/
│ ├── docCache.ts # Blob-backed cache with memory front
│ ├── docService.ts # Main orchestration service
│ ├── tsParser.ts # TypeScript AST parser
│ └── valFetcher.ts # Val Town API client
├── frontend/
│ ├── index.html # HTML entry point
│ ├── index.tsx # React app entry
│ └── components/ # React UI components
│ ├── App.tsx
│ ├── Header.tsx
│ ├── Sidebar.tsx
│ ├── MainContent.tsx
│ ├── FunctionDocCard.tsx
│ ├── ClassDocCard.tsx
│ ├── InterfaceDocCard.tsx
│ ├── TypeDocCard.tsx
│ ├── ConstantDocCard.tsx
│ ├── CodeBlock.tsx
│ └── DocCommentDisplay.tsx
└── shared/
└── docTypes.ts # Shared TypeScript types
- Request → Hono HTTP val receives request
- Cache Check → Check memory cache, then blob storage
- On Cache Miss:
- Fetch val metadata from Val Town API
- Fetch source code from esm.town
- Parse TypeScript AST to extract documentation
- Cache result in blob storage and memory
- Response → Return JSON (API) or rendered HTML (UI)
- Memory Cache: LRU cache (100 entries) for hot paths
- Blob Storage: Persistent cache with 1-hour TTL
- Cache Key: Derived from
username/valname@version - Cache Hit Performance: ~20ms
- Cache Miss: ~2-3 seconds (includes API calls and parsing)
Uses the TypeScript Compiler API to:
- Create an in-memory compiler host
- Parse source files into AST
- Walk nodes to extract declarations
- Parse JSDoc comments using
ts.getJSDocTags() - Generate type signatures and metadata
See shared/docTypes.ts for complete type definitions:
DocManifest- Main documentation manifestFunctionDoc- Function documentationClassDoc- Class documentationInterfaceDoc- Interface documentationTypeAliasDoc- Type alias documentationConstantDoc- Constant/variable documentationDocComment- Parsed JSDoc commentValMetadata- Val Town metadata
Main orchestration service:
// Generate docs with caching
await generateDocs(val: string, opts?: { refresh?: boolean })
// Refresh cache
await refreshDocs(val: string)
// Get cached docs only
await getCachedDocs(val: string)
// Clear cache
await clearValCache(val: string)
await clearAllCaches()
Val Town API client:
// Fetch val bundle
await valFetcher.fetchLatest(val: string): Promise<ValBundle>
TypeScript AST parser:
// Parse val bundle to documentation
parseValBundle(bundle: ValBundle): DocManifest
Documentation cache:
// Create cache instance
const cache = createDocCache({ ttlMs: 3600000, blobPrefix: "doc-cache" })
// Cache operations
await cache.get<T>(key: string)
await cache.set<T>(key: string, data: T, metadata: { version: string })
await cache.has(key: string)
await cache.delete(key: string)
- Clone this repository
- Deploy to Val Town as an HTTP val
- Test with a public val:
https://docs-gen.val.run/?val=stevekrouse/example
This project is designed to run as a Val Town HTTP val. The entry point is
backend/docGenerator.http.ts.
To deploy:
- Create a new HTTP val in Val Town
- Copy the entire project structure
- Point to
backend/docGenerator.http.tsas the entry point
- First Request (cache miss): 2-3 seconds
- Cached Request: 20-50ms
- Cache TTL: 1 hour
- API Calls per Request: Max 2 (metadata + source)
- Public vals only - No authentication for private vals
- Single file vals - Multi-file projects not yet supported
- Basic syntax highlighting - No Prism.js integration yet
- No version history - Only latest version supported
- Rate limiting - Not yet implemented (planned)
- Rate limiting to prevent abuse
- Support for private vals with authentication
- Multi-file val/project support
- Version history and diffing
- Enhanced syntax highlighting with Prism.js
- Export to Markdown
- Custom theming
- Metrics and analytics dashboard
This is a Val Town project. To contribute:
- Fork the val
- Make your changes
- Test thoroughly
- Submit a pull request with clear description
MIT License - see LICENSE file for details
Built with:
- TypeScript Compiler API
- Hono - Web framework
- React - UI library
- Twind - Tailwind CSS-in-JS
- Val Town - Serverless platform
Need help? Open an issue or reach out on Val Town Discord.