Docs / Share an app with clients

Share an app built with AI (OpenCode, Claude Code, Cursor) with clients

Your app is ready in OpenCode (or Claude Code, Cursor, Bolt) and runs at http://127.0.0.1:5173. That address cannot be shared: 127.0.0.1 means this computer itself, so when your client opens it, their browser looks for the app on their own computer. This guide gives three ways to let your client open it.

Pick a way

A. Preview from your computerB. Online from GitC. Static site
Good forQuick demo, feedback from the client todayHanding over to the client, used every dayApps without a backend (output of npm run build)
Addressname-app.hack.id (HTTPS)Your or your client's domain (automatic HTTPS)Your or your client's domain
Your computer must stay onYesNo, runs on a serverNo
RevisionsVisible immediatelyEvery Git push deploys automatically; a preview per pull requestUpload the build folder again
Ready in±5 minutes±10 minutes±5 minutes

Suggestion: use A for the demo, then B once the client agrees. Want OpenCode to do everything, from an empty server to online? See From an empty VM to online.

A. Preview from your computer (tunnel)

Saka opens an outbound connection from your computer to the internet, so you need no public IP and no router ports.

  1. Install the Saka agent on the computer running the app. Linux: see Add a server. Windows: run OpenCode and the app in WSL2, then install the agent in WSL2 (WSL2 guide). Mac: see the Mac section below.
  2. Allow the tunnel address in Vite. Recent Vite versions reject hosts other than localhost ("Blocked request. This host is not allowed"). Add to vite.config:
    vite.config.ts
    export default defineConfig({
      // ...other settings unchanged
      server: { allowedHosts: ['.hack.id'] },
      preview: { allowedHosts: ['.hack.id'] },
    })
  3. Serve the build, not dev mode (faster and lighter for your client):
    Terminal
    npm run build
    npx vite preview --port 4173
    Dev mode (npm run dev, port 5173) works too, but every page loads slower from far away.
  4. In the panel, Tunnel menu: enter a name (e.g. demo-shop), pick your computer's server, choose another web app, enter port 4173, then Create address.
  5. Send https://demo-shop-app.hack.id to your client. New addresses are reviewed by the Saka team first (usually quickly) and you are notified on Telegram.

During the demo, the computer must stay on and awake, and vite preview must keep running. Anyone who knows a tunnel address can open it: do not use real data, and delete the tunnel after the demo. Saka monitors the address and alerts you if it cannot be opened.

Let OpenCode do it. Once Saka is connected to OpenCode, just write:

Prompt
Allow the .hack.id host in the server and preview sections of vite.config, run npm run build then vite preview on port 4173, then create a Saka tunnel named demo-shop to port 4173 on my laptop server and tell me the address.

Using a Mac?

The Saka agent only runs on Linux, so on a Mac way A needs a virtual machine first. Two options:

B. Always online from Git

  1. Put the code on GitHub/GitLab/Gitea. Ask OpenCode: "initialize git, add a .gitignore, commit, and push to a new repo". Private repos work too (Saka gives you a deploy key).
  2. In the panel: Sites, Create site, App from Git, enter the repo address and branch, pick a server and domain. Vite, Next.js, Express, and more are detected automatically via Railpack; a Dockerfile is used when present.
  3. Point the domain's A record to the server IP. HTTPS is set up automatically. No domain yet? Use a name.IP-with-dashes.sslip.io address as the site's domain, e.g. shop.159-223-87-126.sslip.io: automatic HTTPS with no DNS setup, good for demos (use your own domain for production). Or a tunnel for a name-app.hack.id address.
  4. API keys and other secrets go in the Environment variables card, not in the code.
  5. Add the webhook (instructions on the app page): every push deploys with no downtime, and a bad release can be rolled back with one click.

Revisions with your client: turn on Pull request previews. Every change you propose in a pull request gets its own address for the client to check before it is merged.

C. Static site

For apps without their own backend (everything runs in the browser):

  1. Run npm run build. The result is the dist folder.
  2. In the panel: Sites, Create site, choose Static, enter the domain.
  3. Upload the contents of dist to the www folder over SFTP (login details on the site page, e.g. with FileZilla).

Single-page apps (React Router and similar) that open deep addresses like /products/12 are safer with way B, because a static server answers 404 for addresses that are not files.

From an empty VM to online: hand it to OpenCode

Once Saka is connected to OpenCode, the whole road from an empty server to an HTTPS address can be done by OpenCode. You only do the few things that must come from you:

StepWhat OpenCode does (through Saka)What you do
1. ServerIf a cloud account (DigitalOcean, Vultr, IDCloudHost) is connected: offers locations and sizes, then creates the server and installs the agent automatically. If you create the VM yourself: asks Saka for the one-line install command.Approve creating the server (it costs money). The provider's API token is entered only by you in the panel (Settings, Cloud accounts), never in chat. Or create an Ubuntu VM yourself and run the install command on it.
2. CodeSets up Git (.gitignore without .env), commits, and pushes to a repo.Give the repo name and say whether it is private.
3. AddressUses your domain, or a name.IP-with-dashes.sslip.io address (automatic HTTPS, no DNS).With a domain: point its A record to the server IP.
4. DeployCreates the app from Git, fills variables from your local .env, waits for the build, opens the address to confirm it works, and reads logs if it fails.Private repo: paste the deploy key into the repo (once).
5. RevisionsRedeploys, rolls back, and sets up pull request previews for the client.Approve changes on the server.

An opening message you can paste into OpenCode:

Prompt
Call Saka's panduan_deploy tool first and follow its steps. Put the project in this folder online on a Saka server so my client can open it at an HTTPS address. Ask me about the repo, domain, and server first. Never write keys or passwords in the chat.

The panduan_deploy tool gives OpenCode the same steps and rules as this page.

If you create an Ubuntu VM yourself

  1. Create an Ubuntu 22.04 or 24.04 VM at any provider: at least 1 vCPU and 2 GB RAM, with a public IPv4. In the provider's firewall, open ports 22, 80, and 443.
  2. Ask OpenCode to call server_tambah, or open the panel: Servers, + Add server. You get a one-line command.
  3. Log in to the VM (ssh root@SERVER-IP or the provider's web console), paste the command, and press Enter. The server shows up in Saka within seconds, and from then on OpenCode manages it through Saka with no more SSH. New servers are protected by Saka Shield right away.
A VPS that already runs CasaOS, nginx, or Apache?

No problem: in the Readiness card, on the Web ports (80/443) row, press Set up. The old service is moved to another port and stays reachable from the server address, then Saka takes ports 80/443 (details). OpenCode can do it through server_perbaiki with your approval. If ports 80/443 are used by another program (e.g. a Docker container), use a clean VM.

What to watch in the app

Connect Saka to OpenCode

Create a token in the panel (Settings, API tokens), then add it to your project's opencode.json (or ~/.config/opencode/opencode.json):

opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "saka": {
      "type": "remote",
      "url": "https://app.saka.work/mcp",
      "headers": { "Authorization": "Bearer <token>" }
    }
  }
}

OpenCode can then create tunnels, deploy apps from Git, and watch deploys through Saka, with your approval for actions that change a server. Do not commit a file containing the token to a public repo. Full tool list: Connect AI (MCP).