Skip to main content
Wiki and public docs

Wiki and public docs

Every repo carries a wiki — markdown pages stored as a separate Git repository inside Forgejo. fremforge layers an opt-in public mirror on top: enable it once, and the same wiki content is published as anonymous-readable pages at frem.sh/<org>/<repo>/wiki — shareable without a fremforge login.

The surfaces

SurfaceURLAudienceAuth
Internal wikifrem.sh/<org>/<repo>/wiki (when signed in)Repo collaboratorsForgejo session
Public docs mirrorfrem.sh/<org>/<repo>/wiki (anonymous)WorldNone
SSO-gated docsfrem.sh/<org>/<repo>/wiki (anonymous → your IdP)Anyone in an allowed IdP groupYour identity provider — no fremforge seat

Same URL, cookie-conditional routing at the edge. A signed-in collaborator still sees the Forgejo-native wiki with the edit button + history; an anonymous visitor sees the cleaner public docs render of the same content — or, when the repo is SSO-gated, is sent to your identity provider to sign in first (see SSO-gated access).

Enabling the public mirror

Org admin → Public docs (under the Content sidebar group). Pick a repo from the list, then in its panel:

  1. Turn on Publish as docs site.
  2. Choose Access: Public (anyone) or SSO-gated (sign-in required — see below).
  3. (Optional) Drop a small CSS snippet into Custom CSS to brand the render — header colours, font choices, accent lines. The textarea caps at 8 KB and the < character is rejected at submit (prevents </style> HTML injection from leaking into the rendered page; CSS doesn’t legitimately need <).
  4. Save.

The docs site goes live within a few seconds. Revert by turning Publish off at any time — the route falls back to Forgejo’s native rendering, which means anonymous visitors see whatever Forgejo would have served (login for private repos, native wiki HTML for public repos).

SSO-gated access

Docs are anonymous by default. For a repo whose documentation should be internal — readable by your people but not the open internet — set Access to SSO-gated. Readers then sign in with your own identity provider and must be in a group you allow. Two things make this cheap:

  • No fremforge seat is consumed, and no Forgejo account is created. A docs reader is a pure token + group check against your IdP — they never become a member of your org. You can open internal docs to your whole company without buying a seat per reader.
  • It reuses the SSO connections you already have. Any OIDC provider you’ve connected for sign-in is automatically available to gate docs — pick one per repo.

Setting it up

Org admin → Public docs → pick the repo, then in Access:

  1. Set Access to SSO-gated.
  2. Choose the Identity provider — any OIDC connection from your SSO settings.
  3. List the Allowed groups (comma- or newline-separated). A reader needs to be in at least one. These are the same group names you use for team mapping.
  4. Save.

One-time provider setup

Because fremforge signs the reader in directly, your IdP’s OIDC client needs to allow one redirect URI:

https://frem.sh/_app/docs-auth/callback

Add it once per provider (not per repo). The Access panel shows the exact URI to copy. Then use the Test sign-in button on the repo — it runs the real sign-in in a new tab and reports the groups your IdP returned, so you can confirm the redirect URI is registered and set Allowed groups correctly. A ✓ Verified badge appears once a test succeeds. If the redirect URI is missing, your provider shows its own “redirect URI mismatch” error during the test — fix it there and re-test.

What readers see

A reader opens frem.sh/<org>/<repo>/wiki, is sent to your identity provider to sign in (or rides an existing IdP session), and lands back on the docs. The session lasts about 45 minutes, then silently re-checks with your IdP. A reader who signs in but isn’t in an allowed group gets a clear “no access” page rather than the documentation. MFA and its level are entirely your IdP’s call — fremforge only checks a valid token and group membership.

Using a provider only for docs

Want an identity provider that gates docs but grants no git or repository access at all — for example a broad “all-staff” directory? Add it as a normal SSO connection, but leave its group→team mappings empty. Its users can read docs (when they’re in an allowed group) yet map to no team, so they get no seat and no repository access. Readers reaching docs never get a Forgejo account at all; and if such a person ever signs into the git UI directly, they land in no org and the account is cleaned up automatically.

Authoring

Public docs renders the same wiki content Forgejo stores — edit the wiki the normal way (the Wiki tab on the repo, Forgejo’s markdown editor, or by cloning <repo>.wiki.git and pushing markdown). There is no separate authoring surface. What you write is what the public sees.

Supported features:

  • GitHub-Flavored Markdown via marked.
  • Mermaid diagrams. ```mermaid code fences render client-side via mermaid.min.js (~3 MB, served same-origin from /static/lib/, immutable-cached at the edge).
  • Syntax highlighting for code fences via Prism (also same-origin).
  • Print to PDF. Pure print CSS — Cmd+P / Ctrl+P produces a clean A4 / Letter render. No headless-Chrome dependency, no server-side PDF rendering.
  • Sidebar navigation. Grouped into sections you control with a _Sidebar page — see Sidebar navigation below. Without one, the menu is generated automatically.

Not supported (yet):

  • Per-page metadata or front matter
  • Comments
  • Custom domain pointing (e.g. docs.acme.com → the public mirror). Track this on the platform roadmap.

Sidebar navigation

The left-hand menu groups your pages into sections. You control those sections from the wiki itself by adding a page named exactly _Sidebar — the same special-page convention Forgejo uses. No _Sidebar page means the menu is generated for you (see Without a _Sidebar page below), so this is entirely opt-in.

The _Sidebar page is plain markdown. A heading starts a section; the list items beneath it become the links in that section, in the order you write them:

  • A ## Heading line (any level #######) starts a new section.
  • A list item - [Title](Target) becomes a link. Title is what shows in the menu; Target is the wiki page it links to.
  • List items written before the first heading form an untitled group at the top (handy for a lone “Home” link).

Template

Create a wiki page named _Sidebar with this shape:

- [Home](Home)

## Getting started
- [Quickstart](Quickstart)
- [Install](Install)

## Core concepts
- [Tenants & orgs](Tenants-and-orgs)
- [Permissions](Permissions)

## Operations
- [Backup & DR](Backup-and-DR)
- [Runbooks](Runbooks)

Worked example

Say your wiki has the pages Home, Quickstart, Tenants & orgs, and Runbooks. This _Sidebar:

- [Home](Home)

## Get started
- [Quick start guide](Quickstart)

## Reference
- [Tenants and orgs](Tenants-and-orgs)
- [Operational runbooks](Runbooks)

renders a menu with Home ungrouped at the top, then a Get started section containing “Quick start guide”, then a Reference section containing “Tenants and orgs” and “Operational runbooks”. Note the menu labels (e.g. “Quick start guide”) are whatever you put in the [...] text — they don’t have to match the page title.

Link targets

The Target in [Title](Target) is the wiki page name. Forgejo turns spaces into hyphens in page URLs, so the page Tenants & orgs is linked as Tenants-and-orgs. Matching is forgiving — case, spaces, and hyphens are normalised — so Tenants and orgs, tenants-and-orgs, and Tenants-and-orgs all resolve to the same page. Two shorthand forms also work if you prefer them:

  • - [[Tenants-and-orgs]] — wiki-link form; the menu label is the page name.
  • - Tenants-and-orgs — bare page name; same as above.

Without a _Sidebar page

If there’s no _Sidebar page, the menu is generated automatically: every wiki page is listed, with a few well-known titles grouped into sections and everything else under Other. Add a _Sidebar page whenever you want explicit control over grouping, order, or labels. The _Sidebar page (and the other Forgejo special pages _Footer and _Header) never appear as items in the menu themselves.

Tip: a malformed _Sidebar (no headings or list items) is ignored — the menu falls back to the automatic one, so a typo can’t leave you with an empty sidebar.

Privacy posture

The mirror is a read-only projection of an existing wiki. fremforge does not:

  • Store anything customer-side beyond the per-repo opt-in row + the optional CSS snippet.
  • Forward visitor IPs or cookies to Forgejo. The mirror’s Forgejo round-trip is a server-side fetch() with no client identifiers.
  • Add tracking, ads, or third-party JS. The only same-origin scripts are mermaid + Prism.

Server-side render uses marked v18’s built-in HTML escaping — raw HTML in the wiki markdown is escaped at render. The mermaid code fence is the one exception that’s intentionally preserved verbatim so the client-side renderer can pick it up.

Who sees what

Same URL, audience-conditional behaviour: signed-in collaborators see the editable wiki with the edit button and history, while anonymous visitors and search engines see the public render of the same content.

Limits

LimitValue
Wiki page size1 MB (Forgejo limit)
Custom CSS per repo8 KB
Pages per wikiNo fixed cap, but listWikiPages is single-call (no pagination) — practical ceiling ~200
Mermaid bundleLoaded once per visitor, cached immutably at the edge

Related

  • Audit logtenant.public_docs.toggle, tenant.public_docs.custom_css_updated, and tenant.public_docs.access_changed (public ↔ SSO-gated, IdP, allowed groups) actions track every change.
  • Authentication policy — public docs is independent of auth-policy. Public visibility is a per-repo opt-in even on orgs with strict IP allowlists. (The mirror does not enforce IP allowlist; it’s intended to be publicly readable.)