@@ -102,7 +102,8 @@ as an `Authorization` header to that forge's API.
102102
103103The options page is forge-agnostic: it renders one token field per forge that
104104declares authentication support (see ` authForges() ` in ` forges.js ` ), so a new
105- authenticated forge needs no options-page change.
105+ authenticated forge needs no options-page change. Self-hosted instances (see
106+ [ Forges] ( #forges ) ) get their own token field too, keyed per instance.
106107
107108For GitHub, create a [ personal access token] [ gh-token ] (classic or
108109fine-grained) — no scope is required for public repositories; grant repository
@@ -121,15 +122,18 @@ in your account settings with repository read scope. For GitLab, create a
121122
122123Forge endpoints are configured in ` forges.js ` , which defines one ** adapter**
123124per forge that normalizes its API and URL quirks behind a common interface,
124- plus a ` forgeForHostname() ` registry lookup.
125+ plus a ` forgeForHostname() ` registry lookup. Single-host forges (GitHub,
126+ Bitbucket) are plain adapter objects; multi-host forges (GitLab, Forgejo/Gitea)
127+ are * families* whose instances — public and self-hosted alike — are built with
128+ ` instanceOf() ` (see [ Families and self-hosted forges] ( #families-and-self-hosted-forges ) ).
125129
126130Here is the interface for each forge:
127131
128132| Member | Purpose |
129133| ------------ | ------------------------------------------------------------------ |
130134| ` label ` | human-readable forge name |
131- | ` hostnames ` | array of hostnames (static forges only) |
132- | ` base_url ` | API URL (static forges only) |
135+ | ` hostnames ` | array of hostnames matched against the page (one per family instance) |
136+ | ` base_url ` | API root URL the endpoint builders are hung off of |
133137| ` parseUrl ` | ` (URL) → { projectKey, repoSlug, filepath, origin } ` or ` null ` |
134138| ` listPRsUrl ` | API endpoint listing the repo's open PRs |
135139| ` pullRequests ` | ` (listResponse) → array of PR objects ` (unwraps paginated envelopes) |
@@ -157,6 +161,32 @@ Supported forges:
157161- ** Codeberg** (Forgejo, Gitea-compatible API): https://forgejo.org/docs/latest/user/api-usage/
158162- ** GitLab** : https://docs.gitlab.com/ee/api/merge_requests.html .
159163
164+ ### Families and self-hosted forges
165+
166+ A forge's API and URL layout are the same across every host running the same
167+ software, so ` forges.js ` factors that shared logic into a * family* and builds
168+ concrete adapters from it with ` instanceOf(family, { hostname, … }) ` . Both the
169+ built-in public forges and the user's self-hosted forges are built this way, so
170+ a self-hosted forge is just an ` instanceOf ` created at runtime by
171+ ` buildSelfHostedForge() ` from an instance the user configured.
172+
173+ Users add instances (a hostname and which software family it runs) on the
174+ options page; they are stored under ` selfHostedInstances ` in
175+ ` browser.storage.local ` , and ` forgeForHostname() ` matches a page against the
176+ built-in forges first, then those instances.
177+
178+ Because Manifest V3 cannot declare arbitrary hosts up front, the options page
179+ ** requests the host permission** for an instance when it is added and releases
180+ it on removal (both need ` optional_host_permissions ` ); the background script
181+ skips an instance until its permission is granted.
182+
183+ Supported self-hosted software:
184+ - ** GitLab** (CE/EE): https://docs.gitlab.com/ee/api/merge_requests.html
185+ - ** Forgejo / Gitea** : https://forgejo.org/docs/latest/user/api-usage/
186+
187+ To support new self-hosted software, define its family and add it to
188+ ` selfHostedFamilies ` .
189+
160190## Internationalization
161191
162192Translations live in ` _locales/<lang>/messages.json ` . The default locale is
0 commit comments