• Townie
    AI
  • Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
peterqliu

peterqliu

staticServer

write html/css/js like a local project
Public
Like
staticServer
Home
Code
9
examples
4
README.md
USAGE.md
animations.js
index.html
index.ts
script.js
H
server.ts
utils.js
Branches
1
Pull requests
Remixes
History
Environment variables
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.
Sign up now
Code
/
README.md
Code
/
README.md
Search
…
Viewing readonly version of main branch: v50
View latest version
README.md

Val Town Static Server

A flexible, exportable static file server for Val Town that can serve HTML, JavaScript, CSS, and other text files from your project directory.

Features

  • πŸš€ Zero configuration - Works out of the box
  • πŸ“ Dynamic file serving - No hardcoded file paths
  • 🎯 Proper MIME types - Automatic content-type detection
  • πŸ”§ Highly configurable - Custom options for advanced use cases
  • πŸ›£οΈ API routes - Mix static files with dynamic endpoints
  • πŸ”Œ Middleware support - Add logging, auth, or custom processing
  • πŸ“± SPA support - Built-in Single Page Application routing
  • ❌ Smart 404 handling - Customizable error responses

Quick Start

Basic Setup

import { quickStaticServer } from "./static-server.ts"; // Serves index.html at root, any .js/.css/.html files by path export default quickStaticServer();

Custom Index File

import { quickStaticServer } from "./static-server.ts"; export default quickStaticServer('/app.html');

Advanced Usage

Custom Configuration

import { createStaticServer } from "./static-server.ts"; const { handler } = createStaticServer({ indexFile: '/index.html', headers: { 'Cache-Control': 'no-cache', 'X-Powered-By': 'My App' }, mimeTypes: { '.ts': 'text/typescript; charset=utf-8' }, notFoundHandler: (pathname) => { return new Response(`Custom 404: ${pathname} not found`, { status: 404, headers: { 'Content-Type': 'text/plain' } }); } }); export default handler;

API Routes + Static Files

import { advancedStaticServer } from "./static-server.ts"; export default advancedStaticServer({ routes: { '/api/health': () => new Response('OK'), '/api/data': () => new Response(JSON.stringify({ message: 'Hello from API!' }), { headers: { 'Content-Type': 'application/json' } }) }, middleware: [ async (req, next) => { console.log(`${req.method} ${new URL(req.url).pathname}`); return await next(); } ] });

Single Page Application (SPA)

import { createStaticServer } from "./static-server.ts"; const { handler, serveFile } = createStaticServer({ notFoundHandler: async (pathname) => { // Serve index.html for routes without file extensions if (!pathname.includes('.')) { return await serveFile('/index.html'); } return new Response('File not found', { status: 404 }); } }); export default handler;

Configuration Options

StaticServerOptions

OptionTypeDefaultDescription
indexFilestring'/index.html'File to serve at root path
notFoundHandlerfunctionBuilt-in 404Custom 404 response handler
errorHandlerfunctionBuilt-in errorCustom error response handler
mimeTypesobjectBuilt-in typesAdditional MIME type mappings
headersobject{}Headers added to all responses

Built-in MIME Types

  • .html β†’ text/html; charset=utf-8
  • .js β†’ application/javascript; charset=utf-8
  • .css β†’ text/css; charset=utf-8
  • .json β†’ application/json; charset=utf-8
  • .txt β†’ text/plain; charset=utf-8
  • .md β†’ text/markdown; charset=utf-8
  • .xml β†’ application/xml; charset=utf-8
  • .svg β†’ image/svg+xml; charset=utf-8

Project Structure

your-project/
β”œβ”€β”€ index.html          # Main HTML file
β”œβ”€β”€ script.js           # JavaScript files
β”œβ”€β”€ style.css           # CSS files
β”œβ”€β”€ static-server.ts    # The server module
β”œβ”€β”€ server.ts           # Your HTTP val
└── api/
    └── data.json       # Static data files

Examples

See the /examples/ directory for complete working examples:

  • basic-server.ts - Minimal setup
  • custom-server.ts - Custom configuration
  • advanced-server.ts - API routes + middleware
  • spa-server.ts - Single Page Application

HTML Integration

Your HTML files can reference any JavaScript or CSS files:

<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="/styles/main.css"> <link rel="stylesheet" href="/components/header.css"> </head> <body> <div id="app"></div> <!-- All these JS files will be served automatically --> <script src="/utils/helpers.js"></script> <script src="/components/header.js"></script> <script src="/app.js"></script> </body> </html>

Error Handling

The server provides helpful error messages:

  • 404 for missing files: "JavaScript file not found: /missing.js"
  • 500 for server errors: "Server error: [error message]"
  • Custom handlers: Override with your own error responses

Best Practices

  1. File Organization: Keep related files in subdirectories
  2. Error Handling: Provide custom 404 pages for better UX
  3. Caching: Use appropriate cache headers for production
  4. Security: Don't serve sensitive files (use proper file extensions)
  5. Performance: Consider middleware for compression, logging, etc.

Migration from Basic Server

If you have an existing basic server, migration is simple:

// Before export default async function(req: Request) { // manual file serving logic } // After import { quickStaticServer } from "./static-server.ts"; export default quickStaticServer();

Contributing

This server module is designed to be:

  • Extensible - Easy to add new features
  • Maintainable - Clear separation of concerns
  • Reusable - Works across different Val Town projects

The main module is in index.ts for easy importing. Feel free to extend it for your specific needs!

FeaturesVersion controlCode intelligenceCLI
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
Β© 2025 Val Town, Inc.