There is no direct access to the filesystem in Val Town. This allows us to deploy and scale your code quickly and efficiently. If you need to read files from within a val, you can via the Val Town API.
Using the SDK
Section titled “Using the SDK”Read a file
Section titled “Read a file”import ValTown from "npm:@valtown/sdk";const vt = new ValTown();const val_id = "your-val-id-here";const response = await vt.vals.files.getContent(val_id, { path: "path/to/file.txt",});const content = await response.text();console.log(content);
Create a file
Section titled “Create a file”import ValTown from "npm:@valtown/sdk";const vt = new ValTown();const val_id = "your-val-id-here";const file = await vt.vals.files.create(val_id, { path: "path", type: "directory",});
Update a file
Section titled “Update a file”import ValTown from "npm:@valtown/sdk";const vt = new ValTown();const val_id = "your-val-id-here";const file = await vt.vals.files.update(val_id, { path: "path/to/file.txt", content: "New file content",});
List files
Section titled “List files”import ValTown from "npm:@valtown/sdk";const vt = new ValTown();const val_id = "your-val-id-here";const files = await Array.fromAsync( vt.vals.files.retrieve(id, { path: "", recursive: true, }));
Using val utils
Section titled “Using val utils”Val Town’s standard library ships with a suite of utility functions like readFile
and serveFile
.
readFile
Section titled “readFile”Reads the contents of a file from the current val.
Signature:
readFile(path: string, metaImportUrl?: string): Promise<string>
Parameters:
path
- The file path to read (with or without leading slash)metaImportUrl
- Optional. Theimport.meta.url
to determine which val to read from. Defaults toDeno.env.get("VALTOWN_ENTRYPOINT")
Example:
import { readFile } from "https://esm.town/v/std/utils/index.ts";
// Most common usage - reads from current valconst content = await readFile("/README.md");console.log(content);
// Explicit val specificationconst content2 = await readFile("/README.md", import.meta.url);console.log(content2);
listFiles
Section titled “listFiles”Lists all files in the current val with their metadata.
Signature:
listFiles(metaImportUrl?: string): Promise<File[]>
Parameters:
metaImportUrl
- Optional. Theimport.meta.url
to determine which val to list files from. Defaults toDeno.env.get("VALTOWN_ENTRYPOINT")
Example:
import { listFiles } from "https://esm.town/v/std/utils/index.ts";
// Most common usage - lists files from current valconst files = await listFiles();files.forEach((file) => console.log(file.path));
// Explicit val specificationconst files2 = await listFiles(import.meta.url);files2.forEach((file) => console.log(file.path));
listFilesByPath
Section titled “listFilesByPath”Lists files in a specific directory path within the current val.
Signature:
listFilesByPath(path: string, metaImportUrl?: string): Promise<File[]>
Parameters:
path
- The directory path to list files frommetaImportUrl
- Optional. Theimport.meta.url
to determine which val to list files from. Defaults toDeno.env.get("VALTOWN_ENTRYPOINT")
Example:
import { listFilesByPath } from "https://esm.town/v/std/utils/index.ts";
// List files in a specific directoryconst frontendFiles = await listFilesByPath("frontend/");frontendFiles.forEach((file) => console.log(file.path));
httpEndpoint
Section titled “httpEndpoint”Gets the HTTP endpoint URL for a specific file in the val.
Signature:
httpEndpoint(path: string, metaImportUrl?: string): Promise<string>
Parameters:
path
- The file path to get the endpoint formetaImportUrl
- Optional. Theimport.meta.url
to determine which val the file belongs to. Defaults toDeno.env.get("VALTOWN_ENTRYPOINT")
Example:
import { httpEndpoint } from "https://esm.town/v/std/utils/index.ts";
// Get the HTTP endpoint for a specific fileconst endpoint = await httpEndpoint("/api/users.ts");console.log(endpoint); // Returns the full HTTP URL for the endpoint
emailAddress
Section titled “emailAddress”Gets the email address for a file with an email trigger in the val.
Signature:
emailAddress(path: string, metaImportUrl?: string): Promise<string>
Parameters:
path
- The file path to get the email address formetaImportUrl
- Optional. Theimport.meta.url
to determine which val the file belongs to. Defaults toDeno.env.get("VALTOWN_ENTRYPOINT")
Example:
import { emailAddress } from "https://esm.town/v/std/utils/index.ts";
// Get the email address for a file with email triggerconst email = await emailAddress("/handlers/processEmail.ts");console.log(email); // Returns: username-fileid@valtown.email
Notes:
- The file must have an email trigger configured
- Returns email in format:
{username}-{fileIdWithoutDashes}@valtown.email
- Throws an error if the file doesn’t exist or doesn’t have an email trigger
fetchTranspiledJavaScript
Section titled “fetchTranspiledJavaScript”Fetches and transpiles TypeScript/JavaScript code from esm.town URLs.
Signature:
fetchTranspiledJavaScript(url: string): Promise<string>
Example:
import { fetchTranspiledJavaScript } from "https://esm.town/v/std/utils/index.ts";
const code = await fetchTranspiledJavaScript( "https://esm.town/v/std/utils@85-main/index.ts");console.log(code);
Notes:
- Paths can be specified with or without leading slashes
- TypeScript files are automatically transpiled to JavaScript
- Most functions now have optional
metaImportUrl
parameters that default toDeno.env.get("VALTOWN_ENTRYPOINT")
, making them easier to use in most cases
serveFile
Section titled “serveFile”Serves a file from the val as an HTTP Response with the correct Content-Type header.
Signature:
serveFile(path: string, metaImportUrl?: string): Promise<Response>
Parameters:
path
- The file path to servemetaImportUrl
- Optional. Theimport.meta.url
to determine which val to serve from. Defaults toDeno.env.get("VALTOWN_ENTRYPOINT")
Example:
import { serveFile } from "https://esm.town/v/std/utils/index.ts";
// In a Hono app - most common usageapp.get("/assets/*", async (c) => { return await serveFile(c.req.path);});
// Explicit val specificationapp.get("/assets/*", async (c) => { return await serveFile(c.req.path, import.meta.url);});
getContentType
Section titled “getContentType”Determines the appropriate MIME type for a file based on its extension.
Signature:
getContentType(path: string): string
Example:
import { getContentType } from "https://esm.town/v/std/utils/index.ts";
console.log(getContentType("index.html")); // "text/html; charset=utf-8"console.log(getContentType("script.ts")); // "text/javascript"console.log(getContentType("data.json")); // "application/json; charset=utf-8"
Features:
- TypeScript/TSX/JSX files are served as
text/javascript
parseVal
Section titled “parseVal”Parses Val Town metadata from an import.meta.url
.
Signature:
parseVal(importMetaUrl: string): ValMetadata
Example:
import { parseVal } from "https://esm.town/v/std/utils/index.ts";
const val = parseVal(import.meta.url);console.log(val);// Output: { owner: "username", name: "valname", ... }
Prior Art:
staticHTTPServer
Section titled “staticHTTPServer”Creates a Hono-based HTTP server that serves static files from your val. The
server automatically serves /index.html
for root requests and handles all
other file paths.
Signature:
staticHTTPServer(importMetaURL?: string): (request: Request) => Promise<Response>
Parameters:
importMetaURL
- Optional. Theimport.meta.url
to determine which val to serve files from. Defaults toDeno.env.get("VALTOWN_ENTRYPOINT")
Example:
import { staticHTTPServer } from "https://esm.town/v/std/utils/index.ts";
// Most common usage - serves files from current valexport default staticHTTPServer();
// Explicit val specificationexport default staticHTTPServer(import.meta.url);
Features:
- Automatically serves
/index.html
for root path requests (/
) - Handles all file paths with proper content types
- Built on Hono for reliable HTTP handling
- Includes error unwrapping for better debugging
- Returns a fetch-compatible handler function
Use Cases:
- Single-page applications (SPAs)
- Static websites
- Documentation sites
- Asset serving for web applications
Notes:
- The server will attempt to serve
/index.html
for root requests - All other paths are served as-is from the val’s file system
- Non-existent files will throw “Failed to fetch file” errors
- The returned function is compatible with Val Town’s HTTP trigger system
isMain
Section titled “isMain”Checks if the current file is the main entry point of the val. This is a
replacement for import.meta.main
which is not available in Val Town’s
environment.
Signature:
isMain(importMetaURL: string): boolean
Parameters:
importMetaURL
- Theimport.meta.url
of the current file
Example:
import { isMain } from "https://esm.town/v/std/utils/index.ts";
if (isMain(import.meta.url)) { console.log("This file is being run directly"); // Run main logic here} else { console.log("This file is being imported"); // Export functions/classes for use by other files}
Use Cases:
- Conditional execution of code only when file is run directly
- Separating library code from executable code in the same file
- Testing and development workflows
- Creating dual-purpose files that can be both imported and executed
Notes:
- This function compares the provided
import.meta.url
with theVALTOWN_ENTRYPOINT
environment variable - In Val Town, the entry point is determined by which file is being executed directly (e.g., via HTTP trigger, cron, or manual execution)
- This is equivalent to Python’s
if __name__ == "__main__":
pattern or Node.js’srequire.main === module
- Unlike Deno’s
import.meta.main
, this works reliably in Val Town’s serverless environment