Production Checklist
A working deploy and a production site differ in a handful of predictable ways: which portal serves it, how client-side routes resolve, how caches behave across updates, and how new versions ship. Work through each section below before you share a production URL.
Pick the network and portal
The public portal at wal.app serves only Mainnet sites that have a SuiNS name configured. It does not serve Testnet sites, and it does not serve Mainnet sites by object ID alone.
- Production: deploy to Mainnet and attach a SuiNS name, or serve the site under your own domain.
- Testnet or previews: run a local portal for development, or self-host a Testnet portal when others need to open the site. See Mainnet and Testnet portals.
Configure SPA routing
A single-page app serves one index.html and routes in the client, so deep links like /dashboard/settings return 404 unless the site falls back to the index resource. Walrus Sites support this natively with the routes section of ws-resources.json:
{
"routes": {
"/*": "/index.html"
}
}
More specific patterns win over the wildcard, so you can mix real files with client routes. See site configuration for the full route syntax and redirects for sending old paths to new ones.
Control caching and pin versions
Portals and any CDN in front of them cache aggressively, so treat every deployed resource as long-lived:
- Use content-hashed filenames for scripts, styles, and other assets (the default in most bundlers). A stale cache then serves a consistent old version instead of mixing old HTML with new assets.
- Pin a version by keeping the old site object. When
ws-resources.jsoncarries your site's object ID, each deploy updates that site in place; when you need a guaranteed rollback target or a frozen release, publish the release as its own site object and point your name at the object you want to serve. - Expect propagation delay after an update. Caches refresh on their own schedule; verify a fresh deploy from a private browser window or with cache-busting query parameters before concluding an update failed. See troubleshooting if an update never appears.
Name the site with SuiNS
The public portal resolves sites at <name>.wal.app from the SuiNS name that points at your site object. Nested subnames, such as app.myname.wal.app, do not resolve on the public portal; use a separate SuiNS name per site, or serve nested structures under your own domain where your DNS controls the hostname.
Automate updates from CI
There is no built-in watch mode; the supported path to update-on-push is running site-builder deploy from your CI pipeline on every push to your production branch. The GitHub Actions workflow guide walks through the setup, including preparing deployment credentials so the pipeline signs with a dedicated wallet.
One trap decides whether redeploys update your site or duplicate it: site-builder records your site's object ID in ws-resources.json inside the deploy directory, and CI recreates that directory on every run. Commit ws-resources.json to your framework's public/ directory so builds carry it into the output, or pass --object-id explicitly; otherwise every pipeline run creates a new site object and pays for it. See ws-resources.json in pipelines.
Keep the toolchain small
One installer manages the whole toolchain: suiup installs and pins sui, walrus, and site-builder together, replacing separate per-tool installs. See Install the Site Builder. Day-to-day deploys then come down to one command against your build directory.
Port a Next.js app
Walrus Sites serve static files, so a Next.js app must build with static export:
const nextConfig = {
output: "export",
images: { unoptimized: true },
};
next build then writes plain HTML and assets to out/, which you deploy directly (--epochs is required; place ws-resources.json in public/ so redeploys update the same site):
$ site-builder deploy --epochs <NUMBER> ./out
Features that need a server at request time, such as API routes, server actions, and on-demand rendering, do not run on a static host; move that logic to external services or client-side calls. Client-side navigation works with the SPA routing configuration above.