Skip to main content
A static site is plain HTML, CSS, and JavaScript with no server-side code. Landing pages, portfolios, marketing pages, prebuilt SPAs. Nubo has two paths for static sites:
If your repo has…Use
Just an index.html (no package.json)Raypacks static pack (this guide)
A package.json (React, Vite, Astro, etc.)React guide or Node.js guide
A custom nginx config you want to keepPaketo static path below

Raypacks static pack

The Raypacks static pack ships your files behind nginx. No config, no build step.

What you need

  • index.html at the repo root or under public/index.html.
  • No package.json at the root (that triggers the Node pack instead).

Deploy

mkdir my-site && cd my-site
cat > index.html <<'EOF'
<!doctype html>
<title>My site</title>
<h1>Hello from Nubo</h1>
EOF
git init && git add . && git commit -m "init"
# push to GitHub, then in Nubo:
1

New Frame

Open your Project, hit + Frame, pick the repo.
2

Set the port to 80

The static pack serves on port 80.
3

Deploy

Build takes a few seconds. Once it’s live, visit the Frame’s URL.

What gets served

The entire matching directory (the repo root, or public/) is served as-is. CSS files, images, subdirectories — they all work.

Limits

  • No control over nginx (rewrites, redirects, cache headers).
  • No directory listings.
  • No custom 404 page.
If you need any of that, use the Paketo path below.

Paketo with custom config

For SPAs that need URL rewrites, sites that need cache headers, or anything that requires nginx/Apache config tuning, switch the Frame’s Builder to Paketo in Frame Settings.

nginx config

Drop a nginx.conf or set BP_WEB_SERVER=nginx via project.toml:
project.toml
[project]
id = "static-site"
name = "Static site"
version = "1.0.0"

[[build.env]]
name = "BP_WEB_SERVER"
value = "nginx"

[[build.env]]
name = "BP_WEB_SERVER_ROOT"
value = "."

[[build.env]]
name = "BPE_PORT"
value = "8080"
BP_WEB_SERVER_ROOT should match the directory containing your index.html. BPE_PORT sets the runtime port (and the PORT env var); use the same value as the Frame’s port.

Apache config

Same shape, but set BP_WEB_SERVER=httpd:
project.toml
[[build.env]]
name = "BP_WEB_SERVER"
value = "httpd"

Custom configs

If you have your own nginx.conf or httpd.conf at the repo root, Paketo detects it automatically and uses it instead of the generated default. Just drop the file in.

SPAs (React, Vite, Astro)

If your repo has a package.json, the Raypacks static pack won’t pick it up. Two options:
  1. Build locally, ship the output as a static site. Run npm run build, then commit the output directory under public/ (rename if needed). Now the repo has no package.json at the root (move it into a subfolder) and the static pack picks it up.
  2. Let Nubo build and serve. Use the React guide which runs npm run build then serve against the output. Keeps git pushes as the deploy mechanism.
For most apps, option 2 is the right call.