Welcome back

Opening shared build

Preparing your Mach workspace…

Preparing your secure download…

Mach
Dashboard
All guides
Web hosting guide
September 5, 2026 · 9 min read

Ship Your Static Web App with Mach Web Hosting

Deploy Expo web, React Native Web, or Flutter web with immutable previews, stable release aliases, and a clean path from local build to production.
What you will finish with
A linked Mach project, a framework-specific mach.config.json, and an exact command sequence for your first release workflow.

A release workflow for web—not another bucket

A static web release should be easy to review, safe to promote, and even easier to undo. Mach Web Hosting gives every upload an immutable preview URL, then lets Production and Staging point to the exact release you choose. Promotion changes a small route record; it does not overwrite a folder or require another build.
The service accepts the finished output from Expo web, React Native Web, Flutter web, or any static-site tool. Build on your laptop or CI, upload only the output directory, and keep source code, build tooling, and credentials in the environment that already owns them.
Production: project.getmach.dev
Staging: project--staging.getmach.dev
Preview: project--d_<deployment-id>.getmach.dev
Static delivery only: no customer server functions, SSR, database, or backend code is deployed with a site.

1. Claim the address before the first release

Open your project in Mach Dashboard, choose Web Hosting, and set the production subdomain. The project slug is already suggested, so a project named shop-mobile can simply use shop to publish at shop.getmach.dev.
Mach reserves the name globally and locks it when the first deployment is created. That rule is deliberate: links shared with customers, reviewers, and search engines continue to resolve after every future release. Choose the public name carefully, but you never need to choose it again.
One stable name, two release lanes
The Production address stays clean. Staging is explicit in the hostname, and every upload keeps an immutable preview address for a pull request or review thread.

2. Reuse mobile profiles without renaming them

Your mobile build profiles already describe intent such as qa-mobile or store-release. Keep those names. Add a small web block that states which web alias the profile should use and where its finished output will be written.
This separation matters. A profile name is a team convention; a public hostname is a permanent customer contract. Mach reads the mapping explicitly, rather than guessing from a profile name or exposing mobile secrets to a browser bundle.
mach.config.json
{ "build": { "qa-mobile": { "distribution": "internal", "web": { "alias": "staging", "output": "dist" } }, "store-release": { "distribution": "store", "web": { "alias": "production", "output": "dist" } } } }

3. Build locally or in CI, then deploy the output

Mach Web Hosting never turns your dashboard into a remote compiler. The fast path is to build where your app already builds, then upload the resulting static directory. The output needs an index.html file at its root.
For convenience, the CLI can invoke the normal local exporter first: Expo export for Expo and React Native Web projects, or flutter build web --release for Flutter. The upload starts only after that local command succeeds.
bash
# Existing Expo or React Native Web output mach web deploy --output dist # Build locally, then deploy using the profile mapping mach web deploy --build --profile store-release # Flutter builds build/web locally, then deploys it mach web deploy --build --profile qa-mobile
Your files do not pass through the Mach API
The CLI receives short-lived upload URLs and writes static files directly to private R2 storage. The public edge is the only reader of those files.

4. Review an immutable preview, then promote with confidence

Every upload gets a permanent preview URL. Use it for a QA handoff, stakeholder review, or a pull-request comment. Add --no-promote when a deployment should remain a preview rather than move the profile alias immediately.
When the release is ready, promote that exact deployment ID. If a regression escapes, rollback switches the alias to an earlier ready deployment—there is no emergency rebuild, no object overwrite, and no race with a file sync.
bash
mach web deploy --output dist --alias staging --no-promote mach web list mach web promote d_0123abcd --alias production mach web rollback --alias production

5. Keep delivery visible in one release history

The Web Hosting screen is your control plane: choose the address before first deploy, see which immutable release is live for each alias, open previews, and roll back. It also preserves output size, file count, profile, branch, commit, and the deploy message.
Web deployments appear in Mach Release History next to iOS and Android builds. That makes a web release part of the same delivery story as the mobile build or OTA rollout it supports, while still keeping its static-hosting lifecycle clear.

6. Make the same workflow repeatable in CI

CI needs only a Mach token and the same project configuration committed with the app. A profile keeps the output directory and target alias reviewable in code. Mach records Git branch and commit details when the checkout provides them.
Use --no-promote for pull-request or QA previews.
Promote the reviewed deployment ID in a protected release step.
Use the same profile mapping locally and in CI so a branch cannot silently target a different public address.
bash
npm install -g @radhya/mach@latest mach web deploy --build --profile store-release --message "$GIT_COMMIT"

7. Add customer domains later, without blurring environments

The included getmach.dev address is ready from the first deployment. Customer-owned domains are a Premium capability enabled after Cloudflare SSL for SaaS is configured for the Mach zone. That gate means a customer never starts a DNS flow before secure certificate provisioning is ready.
For the initial release, every customer domain serves Production only. Staging remains intentionally private to its explicit Mach address. A static app can call your existing API, but database credentials, private API keys, and other secrets must remain in a backend—not in a browser bundle.
bash
mach web domain add --domain www.customer.com
Keep going
Deploy your first preview
mach web deploy --output dist --no-promote
Get an immutable review link without moving Production or Staging.
Inspect hosted releases
mach web status
See the project address, active aliases, deployments, and domain status.
Build and release with less ceremony.
Guides for Flutter, React Native, and Expo teams that want a clear path from project setup to shipment.
All guides
Start free