Skip to content
HaneDOCS日本語

Build apps

Deploy to Cloudflare

Deploy a Hane app to Cloudflare Workers as a BFF Worker with static assets, and publish it behind Cloudflare Access.

This page describes the general shape of deploying an app built on Hane to Cloudflare Workers. As in the reference app, one Worker serves both the BFF and the screen files, and Cloudflare Access in front of it handles login.

User's browser
│ Cloudflare Access (login)
▼
App Worker
├─ /bff/*, /auth/*, /healthz → BFF (exchanges the Access token with Hane)
└─ everything else → static assets (screens), served with a CSP
│
▼
Hane public API (gateway)
  • The Worker has no bindings to Hane internals and calls the gateway at its public URL. Customer apps always use only the public API.
  • The Worker keeps no sessions. It exchanges the user token that Access adds to each request (Cf-Access-Jwt-Assertion) as the id_token, and reuses the resulting access token in memory only while the same Access token is presented.
  1. Build the screens

    ターミナルウィンドウ
    vite build --config app/vite.config.ts # output goes to app/dist
  2. Write the Worker entry point

    Pass your BFF routes (Hono, for example) a function that looks up the session from the Access token. Pass only paths that are not API routes to the static assets.

    export default {
    fetch(req: Request, env: Env, ctx: ExecutionContext) {
    const app = createApp(env); // routes for /bff/* and /auth/*
    app.get("*", (c) => {
    const path = c.req.path;
    if (path.startsWith("/bff/") || path.startsWith("/auth/")) return c.notFound();
    return env.ASSETS.fetch(c.req.raw);
    });
    return app.fetch(req, env, ctx);
    },
    };

    Treat requests whose Access token has no email address (requests that passed with a service token) as not logged in, because there is no user.

  3. Write the wrangler configuration

    {
    "name": "my-hane-app",
    "main": "bff/worker.ts",
    "compatibility_date": "2026-10-01",
    "assets": {
    "directory": "app/dist",
    "binding": "ASSETS",
    "not_found_handling": "single-page-application",
    "run_worker_first": true
    },
    "vars": {
    "HANE_API": "https://<Hane gateway URL>",
    "HANE_ORG": "acme",
    "HANE_PROJECT": "fleet",
    "HANE_ENV": "prod"
    }
    }

    With run_worker_first, the Worker receives every request first, so it can add the CSP to screens too.

  4. Add secrets

    Put your app’s service account API key in a Worker secret. Never write it in code or in the wrangler configuration.

    ターミナルウィンドウ
    npx wrangler secret put HANE_API_KEY

    In environments where Cloudflare Access also sits in front of the Hane gateway, also store an Access service token for the gateway as secrets, and add the cf-access-client-id and cf-access-client-secret headers to every request to the gateway.

  5. Deploy

    ターミナルウィンドウ
    npx wrangler deploy
  6. Put Cloudflare Access in front

    In the Zero Trust dashboard, create an Access application that covers the Worker’s hostname, and set the login methods and the policy for who may enter. Logout is at /cdn-cgi/access/logout.

  7. Verify

    If the BFF provides /healthz?gateway=1, you can check that it reaches the Hane gateway by getting {"ok":true,"gateway":200}. Finally, log in as a user who is a member of the organization and confirm the screens open. Users who are not members get FORBIDDEN from the token exchange.

  • Create a separate service account and API key for each environment. An API key is bound to one project and environment.
  • Switch values such as HANE_ENV with wrangler’s per-environment configuration; don’t encode environment differences in code.
  • For definitions, promote a ReleaseBundle verified in dev to stage and prod with hanectl release promote. Activation in prod is done by a person with their own login (hanectl).

Let Hane serve the app Preview

Section titled “Let Hane serve the app ”

You can also have Hane serve your app instead of using your own Cloudflare account.

Form What it is
Static app Create a scaffold with hanectl app create and upload files with hanectl app deploy
App container Register a container image after it passes the release gate, the vulnerability check, and signing, and pin it in an Application definition. The app front performs token exchange and passes a short-lived access token with each request, so the container holds no API key

The scope and steps of both forms may change. Check with your provider before using them.