Migrate Val Town code
Turn your vals into a Node.js project and deploy it to an Easel preview.
Move each app's vals into a Git repository as an ordinary Node.js project, then deploy it to a preview. Data and other services come later, in their own guides.
Start with the app
Read the vals before changing them. List each HTTP route and the methods it accepts, each cron and email handler, every import, and every file the vals read at runtime. Vals that share data or import each other belong in one project.
Make the repository private unless every val in it is public.
Imports and runtime
Easel runs Node.js, so Deno-specific imports and APIs change:
- Replace
npm:,jsr:, and package CDN imports such ashttps://esm.sh/with installed packages. Keep the versions that work today. - Copy
esm.townimports into the repository as local files, crediting the source val. - Replace
Deno.env.getwithprocess.env, in server code only. Replace otherDenoAPIs with Node.js or Web APIs, and don't callDeno.serve. - Write relative imports with a
.jsextension, such as./lib/db.js, even for.tsfiles. Node.js needs it at runtime.
A Hono app goes in src/index.ts, exported as the default export:
A val that answers one URL can instead be a file in api/, exporting a
function per HTTP method:
Use one approach per project: an api/ folder hides a Hono app's own /api
routes.
Files and builds
A function sees only the files bundled with it. Read files with a path built
from import.meta.url, such as
readFileSync(new URL("../data/cities.json", import.meta.url)), or import JSON
directly.
| Val Town utility | Replacement |
|---|---|
readFile | A bundled file read, or a JSON or text import |
listFiles, listFilesByPath | A list generated at build time |
serveFile | A file in public/, served by the CDN |
readFileTranspiled, fetchTranspiledJavaScript | A Vite build |
serveImmutableFile, immutableFileUrl | Content-hashed build assets |
hotReload | Your framework's dev server |
httpEndpoint, emailAddress | An environment variable with the new URL or address |
Files in public/ are served before your app, so with Hono, serve the home
page from a route instead of public/index.html. Store anything written at
runtime in a database or object store; a function's filesystem is temporary.
Frameworks
- React and Hono: keep the Vite frontend and the Hono routes.
- Hono JSX: keep server rendering and the JSX settings.
- Better Auth: keep the routes, secret, and user records, and update trusted origins and callback URLs.
- Basic HTML: deploy the static files.
Verify
Deploy a preview from the repository:
Run link first, so the first deployment is a preview rather than production.
Then request each route on the deployment URL with the methods it accepts, and
check the project's logs for errors.
Next, move the app's environment variables.