Skip to content

Git Gateway ​

A drop-in replacement for Netlify's git-gateway. Decap CMS configured with backend: { name: git-gateway } talks to a fixed GitHub repository through a GitHub App installation token, behind a Bearer-token check you supply. It runs on Cloudflare Workers, Node.js, Bun, Deno, or anywhere else Hono runs.

bash
pnpm add @laikacms/git-gateway hono
typescript
import { gitGateway } from '@laikacms/git-gateway';

gitGateway() returns a Hono app to mount in your own.

Options ​

OptionTypeDescription
verifyToken(token: string) => Promise<User | null>Validates the incoming Bearer token. Return null (or throw) to reject.
github{ appId, privateKey, installationId, owner, repo, apiBase? }GitHub App credentials. apiBase defaults to https://api.github.com (useful for GHE).
allowedRolesstring[] (optional)When set, the user returned by verifyToken must have at least one matching role.
logger{ error, warn, info?, debug? } (optional)Pluggable structured logger (pino, bunyan, etc.). Only error and warn are required; info and debug are optional. Defaults to a no-op.
userAgentstring (optional)Custom User-Agent for outgoing GitHub API requests. Defaults to @laikacms/git-gateway.

Endpoints ​

MethodPathAuthDescription
GET/health—Returns { ok: true }. Cheap load-balancer health check.
GET/settings✓Returns { version, github_enabled, roles, user }.
ALL/github/*✓Proxies to https://api.github.com/repos/{owner}/{repo}/* via an installation token.

The /github/* proxy allows only the same subset of endpoints as Netlify's gateway: git/*, contents/*, pulls/*, branches/*, merges/*, statuses/*, compare/*, commits/*, and issues/:n/labels. All other paths return 403 FORBIDDEN.

Usage ​

Mount it inside an existing Hono app:

ts
import { gitGateway } from '@laikacms/git-gateway';
import { Hono } from 'hono';

const app = new Hono<{ Bindings: Env }>();

app.route(
  '/.netlify/git',
  gitGateway({
    verifyToken: async token => {
      const r = await fetch('https://api.github.com/user', {
        headers: { Authorization: `token ${token}`, 'User-Agent': 'gg' },
      });
      if (!r.ok) return null;
      const u = await r.json();
      return { id: String(u.id), email: u.email, name: u.name };
    },
    github: {
      appId: env.GITHUB_APP_ID,
      privateKey: env.GITHUB_APP_PRIVATE_KEY,
      installationId: env.GITHUB_APP_INSTALLATION_ID,
      owner: 'acme',
      repo: 'website',
    },
  }),
);

Then in your Decap CMS config:

yaml
backend:
  name: git-gateway
  gateway_url: https://your-worker.dev/.netlify/git

Released under the MIT License.