g7 — Object Storage/Overview

g7 — Object Storage

g7 is the object storage service built into tissue.systems. The name is a numeronym: g + 7 (the seven letters of lycogen) + n = glycogen — the same convention behind i18n (internationalisation) and k8s (Kubernetes). Glycogen is the molecule animals use for compact, stable energy storage; g7 is where your Cells store their files and binary objects.


What g7 is

g7 provides key-value object storage organised into buckets. Each object is identified by a key (a path-like string) and can hold any content — images, PDFs, JSON blobs, compiled assets, or arbitrary binary data.

Objects are:

  • Durable — stored redundantly and persistent across redeploys
  • Scoped to your account — bucket names are namespaced per user
  • Accessible from Cells — via the env.<BINDING> object at runtime

Creating a bucket

ribo bucket create my-bucket

Bucket names must be lowercase alphanumeric with hyphens.


Binding a bucket to a Cell

In ribo.toml:

[[bindings]]
type    = "g7"
binding = "IMAGES"
bucket  = "user-avatars"

The binding appears as env.IMAGES inside the Cell. You can bind multiple buckets:

[[bindings]]
type    = "g7"
binding = "UPLOADS"
bucket  = "raw-uploads"

[[bindings]]
type    = "g7"
binding = "PROCESSED"
bucket  = "processed-images"

Using g7 in a Cell

export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    if (request.method === "PUT" && url.pathname.startsWith("/upload/")) {
      const key = url.pathname.slice(8);
      await env.UPLOADS.put(key, request.body, {
        httpMetadata: { contentType: request.headers.get("content-type") ?? "application/octet-stream" },
      });
      return Response.json({ ok: true, key });
    }

    if (url.pathname.startsWith("/file/")) {
      const key = url.pathname.slice(6);
      const obj = await env.UPLOADS.get(key);
      if (!obj) return new Response("Not found", { status: 404 });
      return new Response(obj.body, {
        headers: { "content-type": obj.httpMetadata?.contentType ?? "application/octet-stream" },
      });
    }

    return new Response("Not found", { status: 404 });
  },
};

See also