Migrate Val Town blobs
Copy a val's std/blob data to an S3-compatible object store.
Easel doesn't host object storage yet. Move std/blob data to an
S3-compatible store such as Cloudflare R2
and read it with the AWS SDK. Create one private bucket for Preview and one
for Production.
Export from Val Town
A val's blob store is only reachable from that val, so before December 10,
2026, add this export endpoint as a new HTTP file in the original val. Set a
random BLOB_EXPORT_TOKEN in its environment variables and PREFIX to the key
prefix the app writes. For an account-wide store, import from
https://esm.town/v/std/blob instead.
blob-export.ts
Copy the blobs
This script copies every key the endpoint lists, checking each upload's
SHA-256 hash. It needs BLOB_EXPORT_URL, BLOB_EXPORT_TOKEN, BLOB_PREFIX,
S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, and, for R2,
S3_ENDPOINT.
copy-blobs.mjs
Copy to the Preview bucket while Val Town still takes writes:
It's safe to run again, and stops rather than overwrite a blob that changed since the last run.
Update the code
std/blob | AWS SDK |
|---|---|
blob.get, blob.getJSON | GetObjectCommand |
blob.set, blob.setJSON | PutObjectCommand |
blob.delete | DeleteObjectCommand |
blob.list | ListObjectsV2Command, following NextContinuationToken |
blob.copy, blob.move | CopyObjectCommand, then DeleteObjectCommand to move |
Mark private files Cache-Control: private, no-store when a route serves them.
Switch to production
After you freeze writes on Val Town, run the final sync against the Production bucket:
It copies new and changed blobs, then lists the objects it would delete because Val Town no longer has them. Check the list, then apply it:
Back to the feature list.