Static Sites
g7 and the files binding let you deploy a directory of static files (HTML, CSS, JavaScript, images, and any other assets) directly to tissue.systems. No Cell code required for the common case.
The static shorthand
The simplest way to deploy a static site is the static field in ribo.toml:
[cell]
name = "my-site"
static = "./public"That's the entire configuration. ribo deploy will:
- Create a g7 bucket for your files
- Upload every file in
./public(recursively) - Generate a pass-through Cell that routes all requests through the file tree
- Deploy it to a live URL
ribo deploy
# deployed my-site
# address ab1cd2
# url https://my-site.strand-9c.tissue.dev
# files FILES→ab1cd2-files (12 files)Routing behaviour
The file-serving layer follows standard static site conventions:
| Request path | File served |
|---|---|
/ |
index.html |
/about |
about (exact, if exists), then about/index.html |
/css/style.css |
css/style.css |
/missing |
404.html (if exists), otherwise a plain 404 |
Every path is first tried exactly as requested. If an extension-less path doesn't match a file, <path>/index.html is tried as a fallback, enabling clean URLs for multi-page sites.
Directory structure example
public/
index.html
about/
index.html
css/
style.css
js/
app.js
404.htmlDeploy with:
ribo deployAll files are uploaded at deploy time and served from g7. Subsequent ribo deploy calls re-upload the full directory, replacing any previously uploaded files.
Hybrid: static files + dynamic logic
For sites that need both static assets and a server-side API, use the files binding alongside a JS Cell:
[cell]
name = "my-app"
js = "./cell.js"
build = "npm run build"
[[bindings]]
type = "files"
binding = "ASSETS"
dir = "./dist"In the Cell, serve static assets for most paths and handle API routes yourself:
export default {
async fetch(request, env) {
const url = new URL(request.url);
// API routes
if (url.pathname.startsWith("/api/")) {
return handleApi(request, env);
}
// Everything else: static files
return env.ASSETS.fetch(request);
},
};env.ASSETS.fetch(request) applies the same routing rules as the static shorthand: it serves index.html for directory paths and returns a 404 for missing files.
Updating files
Re-running ribo deploy re-uploads the entire directory. The live URL immediately serves the new files. There is no separate "sync" step.
See also
- g7 Overview
- g7 API Reference: direct object access via
get(),put(),delete() - ribo.toml Reference: full config schema