Using Images in Documentation

This document explains how our internal Hugo document, hosted on Cloudflare Pages and parotected by Cloudflare Zero Trust Access (Google SSO), fetches binary assets (images, diagrams, PDFs, etc.) securely

1. Architecture & Connection #

The assets in R2 bueckt are accessed securely from browser by verifying the JWT with ACCESS_TEAM and ACESS_AUD.

+--------------------------+     +------------------------+     +----------------------+
|                          |     |                        |     |                      |
|   Browser (User)         |────▶|  Cloudflare Access     |────▶|  Cloudflare Pages    |
|(docs.internal.gotofu.com)|     |  (Zero Trust / Google) |     |  (Static Content)    |
|                          |     |                        |     |                      |
+--------------------------+     +------------------------+     +----------┬-----------+
                                                                           │
 User requests /docs/... (HTML)                                            │
    - If not logged in, Access triggers Google SSO                         │
    - After login, Access injects `Cf-Access-Jwt-Assertion` header         │
                                                                           ▼
                                                                 +------------------+
                                                                 |  Pages Function  |
                                                                 | (/media/[[path]])|
                                                                 +--------┬---------+
                                                                          │
️Browser requests /media/docs/.../image.png                               │
   → Pages Function receives request + JWT header                         │
                                                                          ▼
                                                            +----------------------------+
                                                            | Verify Access JWT          |
                                                            | (using ACCESS_TEAM/AUD)    |
                                                            | via Access JWKS endpoint   |
                                                            +-------------┬--------------+
                                                                          │
 On successful verification:                                              │
                                                                          ▼
                                                            +-----------------------------+
                                                            | Fetch object from R2        |
                                                            | (bound as DOCS_ASSETS)      |
                                                            | /docs/<section>/<page>/<img>|
                                                            +-------------┬---------------+
                                                                          │
 Return image data                                                       │
                                                                          ▼
                                                             +----------------------------+
                                                             | Cloudflare Edge Cache      |
                                                             | (private, JWT-protected)   |
                                                             +-------------┬--------------+
                                                                           │
 Browser receives image (200 OK)                                           │
   Image displays within the Hugo docs page                                │
                                                                           ▼
                                                             +----------------------------+
                                                             | Cloudflare R2 (Private)    |
                                                             | docs-assets bucket         |
                                                             | Mirrors Markdown structure |
                                                             | e.g. /docs/foo/bar/img.png |
                                                             +----------------------------+

2. Developer Workflow #

Uploading Images #

Start simple and improve later.

A. Manual Upload #

  1. Open the R2 bucket, tofu-internal-docs-medias, in the Cloudflare dashboard.
  2. Create a directory. Refer to Image Path Convention for rules of image paths.
  3. Upload.

B. CLI Upload #

Install Wrangler v3+.

e.g.

# One-time: set credentials
export CF_ACCOUNT_ID=<id>
export CF_API_TOKEN=<token>

# Upload one file
wrangler r2 object put docs-assets/infra/overview/overview.png --file=./overview.png

# Or sync a folder
wrangler r2 object put docs-assets --dir ./images --path-prefix infra/

Referencing Images in Hugo #

You can refernce the image in R2 bucket with following rule.

Make sure you have `/media` prefix.
![image tag](/media/path/to/image/in/r2)

e.g.
![System overview](/media/infra/overview/overview.png)

Image Path Convention #

To keep R2 organized and aligned with the Hugo content structure, every image’s R2 key (path) must mirror the location of the Markdown file where it is referenced.

If you add an image dummy.png to <hugo root>/content/docs/foo/bar.md then its path in R2 must be /docs/foo/bar/dummy.png