{
  "manifest_version": "1",
  "slug": "migrate-val-town",
  "title": "Vals from Val Town",
  "headline": "Move your vals off Val Town",
  "description": "Val Town shuts down on January 10, 2027. Move your HTTP, cron, and email vals, with their SQLite, blobs, and secrets, to one exe.dev VM, same code.",
  "category": "migration",
  "tags": [
    "val town",
    "val town shutdown",
    "val town alternative",
    "migrate from val town",
    "vals",
    "deno",
    "http vals",
    "cron vals",
    "email vals",
    "std/sqlite",
    "std/blob",
    "std/email",
    "val.run",
    "systemd timers"
  ],
  "url": "https://exe.dev/deploy/migrate-val-town",
  "markdown_url": "https://exe.dev/deploy/migrate-val-town.md",
  "upstream": {
    "website": "https://www.val.town",
    "source": "https://github.com/denoland/deno",
    "docs": "https://docs.val.town/migration",
    "license": "MIT (Deno); your vals are yours"
  },
  "example_vm_name": "my-vals",
  "time": "1 hour",
  "stack": [
    {
      "name": "Deno 2.9",
      "detail": "Runs each val's code as it ran on Val Town"
    },
    {
      "name": "The val kit",
      "detail": "Runs triggers, and stands in for std/sqlite, std/blob, std/email, and std/openai",
      "data": "~/vals-kit"
    },
    {
      "name": "Your vals",
      "detail": "One directory per val, with its code, `.env`, and data",
      "data": "~/vals/\u003cval\u003e"
    },
    {
      "name": "systemd",
      "detail": "A service per HTTP val, a timer per cron val, the mail router, and the front door",
      "port": 8000
    }
  ],
  "access": [
    {
      "url": "https://my-vals.exe.xyz/\u003cval\u003e/",
      "who": "private",
      "what": "HTTP vals with `PUBLIC=1`, through the front door; public once you share the VM"
    },
    {
      "url": "https://my-vals.exe.xyz:8001/",
      "who": "private",
      "what": "one HTTP val on its own port (8001, 8002, …), for you only"
    },
    {
      "url": "\u003cval\u003e@my-vals.exe.xyz",
      "who": "public",
      "what": "the address of an email val, once you turn on receiving email"
    }
  ],
  "inputs": [
    {
      "name": "VAL_TOWN_API_KEY",
      "description": "a Val Town API token with read access to vals (Settings → API Tokens); only to list and export your vals, and leave it out to move only public vals"
    },
    {
      "name": "VALS",
      "description": "which vals to move, written `user/val`; leave empty for all of them"
    }
  ],
  "delivers": [
    "Every val's code exported to `~/valtown-export`, with each file's trigger and the names of its environment variables.",
    "HTTP vals running as services that restart on reboot, each on its own private port, and the ones you choose at `https://\u003cvm\u003e.exe.xyz/\u003cval\u003e/`.",
    "Cron vals on systemd timers, in UTC, with `lastRunAt` carried from run to run.",
    "Email vals answering mail to `\u003cval\u003e@\u003cvm\u003e.exe.xyz`.",
    "std/sqlite, std/blob, std/email, and std/openai working on the VM without code changes.",
    "A report of each val's schedule, secrets, and data to bring over, and any line still calling Val Town."
  ],
  "deployable": true,
  "deploy": {
    "new_vm_url": "https://exe.dev/new?prompt=VAL_TOWN_API_KEY%3D%3Cfill-this-in%3E%0AVALS%3D%3Cfill-this-in%3E%0A%0ASet%20up%20Vals%20from%20Val%20Town%20on%20this%20VM%20by%20following%20the%20exe.dev%20recipe%20at%20https%3A%2F%2Fexe.dev%2Fdeploy%2Fmigrate-val-town.md%20from%20top%20to%20bottom.%0A%0AThe%20values%20at%20the%20top%20of%20this%20message%20are%20mine%3A%0A-%20VAL_TOWN_API_KEY%3A%20a%20Val%20Town%20API%20token%20with%20read%20access%20to%20vals%20%28Settings%20%E2%86%92%20API%20Tokens%29%3B%20only%20to%20list%20and%20export%20your%20vals%2C%20and%20leave%20it%20out%20to%20move%20only%20public%20vals%0A-%20VALS%3A%20which%20vals%20to%20move%2C%20written%20%60user%2Fval%60%3B%20leave%20empty%20for%20all%20of%20them%0AAsk%20me%20for%20any%20that%20still%20say%20%3Cfill-this-in%3E%20before%20you%20need%20them.%0A%0AThe%20recipe%27s%20example%20VM%20name%20is%20my-vals.%20This%20VM%27s%20name%20is%20the%20output%20of%20%60hostname%60%3A%20use%20it%20wherever%20the%20recipe%20writes%20my-vals.%20Skip%20the%20step%20that%20creates%20the%20VM%3B%20you%20are%20on%20it.%0A%0AYou%20are%20done%20when%20all%20of%20these%20are%20true.%20Check%20each%20one%20yourself%3A%0A-%20Every%20val%27s%20code%20exported%20to%20%60~%2Fvaltown-export%60%2C%20with%20each%20file%27s%20trigger%20and%20the%20names%20of%20its%20environment%20variables.%0A-%20HTTP%20vals%20running%20as%20services%20that%20restart%20on%20reboot%2C%20each%20on%20its%20own%20private%20port%2C%20and%20the%20ones%20you%20choose%20at%20%60https%3A%2F%2F%3Cvm%3E.exe.xyz%2F%3Cval%3E%2F%60.%0A-%20Cron%20vals%20on%20systemd%20timers%2C%20in%20UTC%2C%20with%20%60lastRunAt%60%20carried%20from%20run%20to%20run.%0A-%20Email%20vals%20answering%20mail%20to%20%60%3Cval%3E%40%3Cvm%3E.exe.xyz%60.%0A-%20std%2Fsqlite%2C%20std%2Fblob%2C%20std%2Femail%2C%20and%20std%2Fopenai%20working%20on%20the%20VM%20without%20code%20changes.%0A-%20A%20report%20of%20each%20val%27s%20schedule%2C%20secrets%2C%20and%20data%20to%20bring%20over%2C%20and%20any%20line%20still%20calling%20Val%20Town.%0A%0ARead%20the%20whole%20recipe%2C%20including%20the%20closed%20details%2C%20and%20follow%20%22Move%0Athe%20vals%20by%20hand%22%20in%20order%2C%20skipping%20VM%20creation%3B%20the%20walkthrough%20above%0Ait%20is%20for%20the%20owner.%20Install%20exactly%20the%20pinned%20Deno%20version.%0APut%20the%20API%20key%20in%20~%2F.valtown-api-key%20%28mode%20600%29%20and%20keep%20it%2C%20the%0Aexport%20token%2C%20and%20every%20secret%20value%20out%20of%20your%20replies%20and%20out%20of%0AGit.%20Never%20change%20anything%20on%20Val%20Town%20yourself%3A%20adding%20export-data.ts%2C%0Asetting%20variables%2C%20pausing%20vals%2C%20and%20redirects%20are%20the%20owner%27s%20steps.%0AAsk%20the%20owner%20for%20each%20cron%20val%27s%20schedule%20%28the%20API%20doesn%27t%20return%20it%29.%0ADon%27t%20run%20share%20set-public%20or%20share%20receive-email%3B%20give%20the%20owner%0Athose%20commands.%20Leave%20vals%20whose%20secrets%20are%20missing%20stopped.%0AIf%20a%20val%20uses%20a%20Val%20Town%20feature%20this%20kit%20doesn%27t%20replace%2C%20list%20it%20in%0Athe%20report%20rather%20than%20rewriting%20the%20val.%0AFinish%20with%20the%20report%20from%20%22Check%22%3A%20per%20val%2C%20its%20triggers%2C%20port%2C%0Aschedule%2C%20email%20address%2C%20missing%20secrets%2C%20data%20still%20to%20copy%2C%20and%0Aprepare.ts%27s%20leftover%20lines%3B%20then%20the%20owner%27s%20steps%20in%20%22Make%20the%20move%22.%0A%0AFinish%20with%20the%20URLs%20I%20should%20open.%0A",
    "terminal": "curl -fsSL https://exe.dev/deploy/migrate-val-town/prompt.txt | ssh exe.dev new --prompt=/dev/stdin",
    "prompt": "VAL_TOWN_API_KEY=\u003cfill-this-in\u003e\nVALS=\u003cfill-this-in\u003e\n\nSet up Vals from Val Town on this VM by following the exe.dev recipe at https://exe.dev/deploy/migrate-val-town.md from top to bottom.\n\nThe values at the top of this message are mine:\n- VAL_TOWN_API_KEY: a Val Town API token with read access to vals (Settings → API Tokens); only to list and export your vals, and leave it out to move only public vals\n- VALS: which vals to move, written `user/val`; leave empty for all of them\nAsk me for any that still say \u003cfill-this-in\u003e before you need them.\n\nThe recipe's example VM name is my-vals. This VM's name is the output of `hostname`: use it wherever the recipe writes my-vals. Skip the step that creates the VM; you are on it.\n\nYou are done when all of these are true. Check each one yourself:\n- Every val's code exported to `~/valtown-export`, with each file's trigger and the names of its environment variables.\n- HTTP vals running as services that restart on reboot, each on its own private port, and the ones you choose at `https://\u003cvm\u003e.exe.xyz/\u003cval\u003e/`.\n- Cron vals on systemd timers, in UTC, with `lastRunAt` carried from run to run.\n- Email vals answering mail to `\u003cval\u003e@\u003cvm\u003e.exe.xyz`.\n- std/sqlite, std/blob, std/email, and std/openai working on the VM without code changes.\n- A report of each val's schedule, secrets, and data to bring over, and any line still calling Val Town.\n\nRead the whole recipe, including the closed details, and follow \"Move\nthe vals by hand\" in order, skipping VM creation; the walkthrough above\nit is for the owner. Install exactly the pinned Deno version.\nPut the API key in ~/.valtown-api-key (mode 600) and keep it, the\nexport token, and every secret value out of your replies and out of\nGit. Never change anything on Val Town yourself: adding export-data.ts,\nsetting variables, pausing vals, and redirects are the owner's steps.\nAsk the owner for each cron val's schedule (the API doesn't return it).\nDon't run share set-public or share receive-email; give the owner\nthose commands. Leave vals whose secrets are missing stopped.\nIf a val uses a Val Town feature this kit doesn't replace, list it in\nthe report rather than rewriting the val.\nFinish with the report from \"Check\": per val, its triggers, port,\nschedule, email address, missing secrets, data still to copy, and\nprepare.ts's leftover lines; then the owner's steps in \"Make the move\".\n\nFinish with the URLs I should open.\n",
    "prompt_url": "https://exe.dev/deploy/migrate-val-town/prompt.txt"
  },
  "updated": "2026-11-13",
  "related": [
    "migrate-heroku",
    "migrate-railway",
    "migrate-durable-objects",
    "migrate-lovable",
    "migrate-digitalocean-droplet",
    "migrate-conductor-cloud"
  ],
  "alternatives": [
    "Val Town"
  ],
  "files": [
    "https://exe.dev/deploy/migrate-val-town/blob-global.ts",
    "https://exe.dev/deploy/migrate-val-town/blob-store.ts",
    "https://exe.dev/deploy/migrate-val-town/blob.ts",
    "https://exe.dev/deploy/migrate-val-town/email.ts",
    "https://exe.dev/deploy/migrate-val-town/export-data.ts",
    "https://exe.dev/deploy/migrate-val-town/export-vals.ts",
    "https://exe.dev/deploy/migrate-val-town/front.ts",
    "https://exe.dev/deploy/migrate-val-town/imports.json",
    "https://exe.dev/deploy/migrate-val-town/mail-router.ts",
    "https://exe.dev/deploy/migrate-val-town/openai.ts",
    "https://exe.dev/deploy/migrate-val-town/prepare.ts",
    "https://exe.dev/deploy/migrate-val-town/pull-data.ts",
    "https://exe.dev/deploy/migrate-val-town/pull-env.ts",
    "https://exe.dev/deploy/migrate-val-town/run.ts",
    "https://exe.dev/deploy/migrate-val-town/sqlite-global.ts",
    "https://exe.dev/deploy/migrate-val-town/sqlite.ts"
  ]
}
