g7 — Object Storage/Static Sites

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:

  1. Create a g7 bucket for your files
  2. Upload every file in ./public (recursively)
  3. Generate a pass-through Cell that routes all requests through the file tree
  4. Deploy it to a live URL
ribo deploy
# deployed  my-site
# address   ab1cd2
# url       https://word-ab1c.dev.tissue.systems
# 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/index.html (if exists), then about (exact)
/css/style.css css/style.css
/missing 404.html (if exists), otherwise a plain 404

Paths with a file extension are served directly. Paths without one attempt <path>/index.html first, enabling clean URLs for multi-page sites.


Directory structure example

public/
  index.html
  about/
    index.html
  css/
    style.css
  js/
    app.js
  404.html

Deploy with:

ribo deploy

All 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