Static Apps
Static Apps & deploys
A Static App hosts a website or single-page app on the Ngris edge — no server, no agent, no CLI. Upload a .zip of your built site or connect a GitHub/GitLab repo, and Ngris serves it over global HTTPS with automatic TLS. Every deploy is immutable and versioned, so rollback is an instant pointer flip.
Two pieces work together: an Application is the content (your files, from an upload or a git repo); an agentless Endpoint points at it and gives it a public URL. Unlike a tunnel, there is no agent to run — the content lives on the edge.
install + build in an isolated per-build sandbox, and serves the output. Already-built static files (an index.html at the root, no framework) are served as-is with no build step.
Static Apps require the application_hosting entitlement on your plan. Bandwidth counts against your account's single monthly data-transfer allowance (the same pool as tunnels); over the cap, requests are served a 429 until the period resets.
Quick deploy (one call)
The fastest path from code to a live URL creates the app, its first deploy, and the public endpoint in a single request — and returns the live URL.
Dashboard
Open Applications → New, pick Upload or Connect Git, and follow the wizard. When the build is ready the app is live at its generated URL; add a custom domain any time.
API — upload a built site
curl -X POST "https://api.ngris.com/v1/applications/quick-deploy" \ -H "X-API-KEY: <your_api_key>" \ -F "name=my-site" \ -F "file=@dist.zip" \ -F "wait=true"
API — connect a git repo
curl -X POST "https://api.ngris.com/v1/applications/quick-deploy" \
-H "X-API-KEY: <your_api_key>" \
-H "Content-Type: application/json" \
-d '{"name":"my-site","repo_url":"https://github.com/acme/site","branch":"main"}'
The response includes the live url. Pass wait=true to block up to 90 seconds until the first build is live; otherwise the URL is created immediately and starts serving within a few seconds as the build finishes. See the Quick Deploy API reference for the full response.
Deploy from an upload
Build your site locally, zip the output directory, and upload it. Each upload is a new immutable deploy; the first successful build goes live automatically.
- Run your build (
npm run build,vite build, Hugo…) and zip the output folder (dist/,build/,public/). - Make sure
index.htmlsits at the root of the zip (or set Publish directory to the subfolder that holds it). - Max upload size is plan-limited (default 100 MB).
curl -X POST "https://api.ngris.com/v1/applications/{uuid}/deploys" \
-H "X-API-KEY: <your_api_key>" \
-F "file=@dist.zip"
The build runs asynchronously; poll GET /v1/applications/{uuid}/deploys until the newest deploy reaches ready.
Git push-to-deploy
Connect a GitHub or GitLab repo and every push to the configured branch redeploys automatically. On connect, Ngris runs the first deploy and generates a webhook secret.
1. Connect the repo
Create the app with source: "git" (or use quick-deploy with repo_url). For a private repo, pass a git_token (a GitHub PAT or GitLab token with read access).
2. Register the webhook
Fetch the webhook details with GET /v1/applications/{uuid}/webhook (or copy them from the app's Push to deploy panel), then:
| Provider | Where | Fields |
|---|---|---|
| GitHub | Repo → Settings → Webhooks → Add webhook | Payload URL = url, Content type = application/json, Secret = secret, event = “Just the push event”. |
| GitLab | Settings → Webhooks | URL = url, Secret token = secret, enable Push events. |
Ngris verifies every delivery's signature (GitHub X-Hub-Signature-256 / GitLab X-Gitlab-Token) against the secret, and deploys the exact pushed commit. Rotate the secret any time with POST /v1/applications/{uuid}/webhook/regenerate — remember to update it in the provider afterward.
Serving settings
Tune how files are served with PUT /v1/applications/{uuid} or the app's Serving settings panel:
- Publish directory (
publish_dir) — the subfolder that is your site root (e.g.dist). Leave blank ifindex.htmlis at the archive root. - Index document (
index_document) — served for directory requests. Defaultindex.html. - SPA fallback (
spa_fallback) — serve the index for any unmatched path. Turn this on for React/Vue/Svelte apps that use client-side routing. - Custom 404 (
not_found_path) — a document served for missing paths when SPA fallback is off.
Builds & environment variables
When your source contains a framework (a package.json with a build script, or a Hugo/Jekyll config), Ngris runs the build for you in a locked-down, single-use sandbox: no network except your package registry, no credentials, read-only root, hard CPU/memory/time limits. It installs dependencies, runs the build, and publishes the output directory it detects for your framework (dist/, build/, .next/, public/…).
Environment variables & secrets
Front-end builds need config — API URLs, publishable keys, feature flags. Add them under the app's Environment variables panel (or the API); each one is injected into your build with its exact name, so VITE_API_URL or NEXT_PUBLIC_TOKEN is available to vite build / next build as-is.
- Mark sensitive values as Secret — they're encrypted at rest and never returned by the API or shown in the dashboard again (write-only).
- Changes apply on your next deploy; trigger one with a push or a re-upload.
- Names must match
[A-Za-z_][A-Za-z0-9_]*.
curl -X PUT "https://api.ngris.com/v1/applications/{uuid}/env" \
-H "X-API-KEY: <your_api_key>" \
-H "Content-Type: application/json" \
-d '{"name":"VITE_API_URL","value":"https://api.example.com","is_secret":false}'
List them with GET /v1/applications/{uuid}/env (secret values masked) or remove one with DELETE /v1/applications/{uuid}/env/{name}.
Build logs (live)
Every build’s full log is captured — success or failure — so you can see exactly what ran and why a build broke. Open a deploy’s Log from the Deploys page and it tails live while the build runs; or fetch the log directly (an X-Build-Status response header reports whether the build is still running):
curl "https://api.ngris.com/v1/applications/{uuid}/deploys/{deploy_uuid}/logs" \
-H "X-API-KEY: <your_api_key>"
Preview deploys
Every ready deploy gets its own shareable preview URL — independent of which version is live — so you can review a build before promoting it, or share a work-in-progress. The URL is served read-only from the edge exactly like the live site (same TLS, same speed).
Find it as the Preview link next to any deploy on the Deploys page, or read preview_url from GET /v1/applications/{uuid}/deploys. The URL embeds the deploy’s unguessable id, so it is shareable without exposing your other versions. Promote a preview to live any time with the deploy’s Activate action — an instant, atomic pointer flip.
Custom domain & HTTPS
A Static App is exposed by an agentless endpoint. On a shared domain you get an auto-generated name.ngris.app URL instantly; to use your own domain, add it under Domains, then create the endpoint on it — TLS is provisioned automatically.
curl -X POST "https://api.ngris.com/v1/endpoints" \
-H "X-API-KEY: <your_api_key>" \
-H "Content-Type: application/json" \
-d '{"serving_mode":"agentless","application_uuid":"<app_uuid>","subdomain":"app","is_custom":true,"domain_id":42}'
Everything you can put on a normal endpoint applies here too — auth, firewall, and rate limits all work on agentless endpoints.
Deploys & rollback
Every upload or push creates a new immutable deploy. The app has one live deploy at a time; switching between versions is an atomic pointer flip — no rebuild, no downtime.
List versions with GET /v1/applications/{uuid}/deploys and promote or roll back to any ready version with POST /v1/applications/{uuid}/deploys/{deploy_uuid}/activate. The first successful build activates itself; later versions require an explicit activate.