site-diogenesoftoronto
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Val Town is a serverless platform for running JavaScript/TypeScript code with a unique deployment model focused on "vals" (individual code modules). This document captures key learnings from converting a static site to a React TSX application deployed on Val Town.
- Vals: Individual code modules that can be HTTP endpoints, cron jobs, or email handlers
- File-based deployment: Code is deployed by pushing files via the
vtCLI tool - Branch-based versioning: Each val can have multiple branches (main, dev, etc.)
- No traditional server management: Platform handles scaling, hosting, and infrastructure
# Check status of local changes vt status # Push changes to deploy vt push # Open deployed val in browser vt browse # Clone existing vals vt clone <valUri> [targetDir] # Create new vals vt create <valName> [targetDir]
/** @jsxImportSource https://esm.sh/react@18.2.0 */
import React, { useState } from "https://esm.sh/react@18.2.0";
import { createRoot } from "https://esm.sh/react-dom@18.2.0/client";
- Pinned versions: Always pin React versions to avoid breaking changes
- ESM.sh imports: Use
https://esm.shfor all external dependencies - No build step: Direct browser execution of TSX files
- Functional components with hooks
- TypeScript interfaces for props and state
- TailwindCSS for styling (CDN-based)
- Client-side rendering with
createRoot
<noscript> <!-- Graceful degradation for users without JavaScript --> <div>Content requiring JavaScript...</div> </noscript> <div id="root"></div> <script type="module" src="index.tsx"></script>
- SEO friendly: Search engines can index the fallback content
- Accessibility: Users with disabled JavaScript still get useful content
- Performance: Fast initial load with progressive enhancement
{ "compilerOptions": { "noImplicitAny": false, "strict": true, "lib": ["dom", "dom.iterable", "deno.ns", "deno.unstable"] }, "lint": { "rules": { "exclude": ["no-explicit-any", "no-import-prefix"] } } }
- Deno-specific libs: Include
deno.nsanddeno.unstable - Import prefix rules: Exclude
no-import-prefixto allow ESM.sh imports - Strict mode: Enable but allow
anytypes where needed
<script src="https://cdn.twind.style" crossorigin></script>
<div className="min-h-screen bg-black text-white font-mono p-4 flex items-center justify-center">
<div className="w-full max-w-2xl space-y-8">
{/* Content */}
</div>
</div>
├── index.html # No-JS fallback + React container
├── index.tsx # React app entry point
├── App.tsx # Main component
├── deno.json # Deno configuration
├── CRUSH.md # Agent development guidelines
└── .gitignore # Exclude .vt/, .crush/, etc.
- Entry points:
index.tsxfor React apps - Components: PascalCase (App.tsx, Header.tsx)
- HTML:
index.htmlas the primary file
- No
console.login production (use proper logging) - Limited debugging tools compared to traditional servers
- Network requests must be HTTPS
- No server-side file system access
- Use try/catch for async operations
- Provide user-friendly error messages
- Test with
vt statusbefore pushing - Use
vt tailto monitor logs in production
- Code splitting: Keep components focused and small
- Lazy loading: Import components only when needed
- Bundle size: Monitor via browser dev tools
- Caching: Leverage browser caching for assets
- Cold starts: First request may be slower
- Memory limits: Be mindful of resource usage
- Concurrent requests: Platform handles scaling automatically
# Check TypeScript compilation deno check # Run linter deno lint *.tsx # Test locally (serve static files) python -m http.server 8000
- Make changes locally
- Test with
deno checkanddeno lint - Check
vt statusfor pending changes vt pushto deployvt browseto verify deployment
- No secrets in code: Use environment variables
- Input validation: Sanitize all user inputs
- HTTPS only: All external requests must use HTTPS
- CORS handling: Configure appropriate CORS headers
- Environment variables: Access via
Deno.env.get() - No file system access: Cannot read/write server files
- Sandbox environment: Isolated execution context
// HTTP endpoint val
export default async function(req: Request): Promise<Response> {
// Handle request
return new Response("Hello World");
}
// Cron trigger val
export default async function(): Promise<void> {
// Scheduled task
}
vt status- Check deployment statusvt push- Deploy changesvt pull- Sync remote changesvt browse- Open in browservt create- Create new valsvt clone- Clone existing vals
- Binary files: Cannot upload binary files > certain size
- Database files: SQLite files cannot be deployed
- Empty files: Files must have content
- Version pinning: Always pin dependency versions
- ESM.sh URLs: Use full URLs for imports
- Lint conflicts: Configure linter to allow Val Town patterns
- JSX transform: Must use
@jsxImportSource - Component mounting: Use
createRootfor React 18 - Styling conflicts: TailwindCSS works but may need custom config
- Val Town is perfect for: Small web apps, APIs, scheduled tasks, and rapid prototyping
- React works great: With proper JSX configuration and pinned versions
- Progressive enhancement: Essential for accessibility and SEO
- Deployment is simple: Just
vt pushafter local testing - Platform limitations: Must design around serverless constraints
- TypeScript first: Strong typing is encouraged and well-supported
- ESM.sh ecosystem: Rich ecosystem of packages available via ESM.sh
- Advanced patterns: Custom hooks, context providers, routing
- Database integration: Val Town's built-in SQLite support
- Real-time features: WebSockets and server-sent events
- Multi-val architectures: Coordinating between multiple vals
- Performance optimization: Bundle analysis and code splitting
- Testing strategies: Unit and integration testing approaches
- Val Town Docs
- ESM.sh - Package registry
- TailwindCSS - Utility-first CSS
- React 18 Docs - Latest React features
Documented on: 2025-01-19 Platform: Val Town Project: mcp2cli React TSX conversion skills/val-town-development.md
