Public
Like
staticServer
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.
https://peterqliu--bbdc3bbab0ec11f0a8800224a6c84d84.web.val.run
A flexible, exportable static file server for Val Town that can serve HTML, JavaScript, CSS, and other text files from your project directory.
- π 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
import { quickStaticServer } from "./static-server.ts";
// Serves index.html at root, any .js/.css/.html files by path
export default quickStaticServer();
import { quickStaticServer } from "./static-server.ts";
export default quickStaticServer('/app.html');
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;
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();
}
]
});
import { createStaticServer } from "./static-server.ts";
const { handler, serveFile } = createStaticServer({
importMetaUrl: import.meta.url, // Required!
notFoundHandler: async (pathname) => {
// Serve index.html for routes without file extensions
if (!pathname.includes('.')) {
return await serveFile('/index.html', { importMetaUrl: import.meta.url });
}
return new Response('File not found', { status: 404 });
}
});
export default handler;
| Option | Type | Default | Description |
|---|---|---|---|
indexFile | string | '/index.html' | File to serve at root path |
notFoundHandler | function | Built-in 404 | Custom 404 response handler |
errorHandler | function | Built-in error | Custom error response handler |
mimeTypes | object | Built-in types | Additional MIME type mappings |
headers | object | {} | Headers added to all responses |
.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
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
See the /examples/ directory for complete working examples:
basic-server.ts- Minimal setupcustom-server.ts- Custom configurationadvanced-server.ts- API routes + middlewarespa-server.ts- Single Page Application
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>
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
- File Organization: Keep related files in subdirectories
- Error Handling: Provide custom 404 pages for better UX
- Caching: Use appropriate cache headers for production
- Security: Don't serve sensitive files (use proper file extensions)
- Performance: Consider middleware for compression, logging, etc.
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();
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
Feel free to extend it for your specific needs!