on this page

g7Static 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://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.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