Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
Global admin, ban, and communication management system for the Source
engine.

> [!TIP]
> **Rather not self-host?** [**RookHelm**](https://rookhelm.com?utm_source=sourcebans-pp&utm_medium=referral&utm_content=readme) is a
> commercial, fully-hosted alternative to SourceBans++ with more
> moderation tooling built in. It runs the whole stack for you and
> imports your existing SourceBans++ data. SourceBans++ itself stays
> free and self-hostable, always.

## Links

- **Docs:** <https://sbpp.github.io/> (install, upgrade, configure, FAQ)
Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ shell — all authoring happens here).
| `src/content.config.ts` | Astro content-collection schema. Re-exports Starlight's `docsLoader` + `docsSchema` so the `src/content/docs/` collection is wired with the right loader and front-matter validation. Edit when adding a new collection (none currently). |
| `src/content/docs/` | All page content, organised by sidebar group (`getting-started/`, `setup/`, `troubleshooting/`, …). `.md` for plain pages, `.mdx` for pages that use Starlight components (Tabs, LinkCard, Card, etc.). |
| `src/content/docs/sponsor.mdx` | Canonical sponsor landing page reached via the topbar heart icon, the per-page footer link, and `.github/FUNDING.yml`'s `custom:` URL (issue #1416). Uses `template: splash` (no sidebar) and is intentionally absent from the sidebar tree in `astro.config.mjs`. Renders the funding-platforms list + tier-grouped sponsor roll via `src/components/Sponsors.astro`. |
| `src/content/docs/rookhelm.mdx` | In-docs hub for RookHelm, the commercial hosted alternative to self-hosting SourceBans++. Reached from the top-level `RookHelm` sidebar entry (registered in `astro.config.mjs`), the homepage / overview / data-export callouts, and (indirectly) the header CTA in `src/components/SocialIcons.astro` which links out to the product site. Framed neutrally as a paid alternative; SourceBans++ stays free + self-hostable. **Deliberately avoids enumerating RookHelm's features** — those live on rookhelm.com and would drift stale here, so the page positions in general terms ("more moderation tooling built in") and links out for specifics. It shouldn't need updating when RookHelm's feature set changes. Keep every RookHelm callout on the same general-positioning rule — across the docs (this page + the README / homepage / overview / data-export mentions) AND the one in-panel surface: a subtle, owner-only migration note on the Full data export page (`web/themes/default/page_admin_export.tpl`), placed there because the export bundle is exactly what RookHelm imports. That's the only RookHelm callout inside the shipped panel by design (owner-only, contextual, no public-page / login / sub-admin exposure); don't add panel callouts elsewhere without the same audience + subtlety bar. **Outbound-link tagging:** every link that points straight at `rookhelm.com` (this page's 3 links, the header CTA in `SocialIcons.astro`, the root `README.md` callout, and the panel export-page note) carries a UTM referral tag — `?utm_source=sourcebans-pp&utm_medium=referral&utm_content=<placement>` (`docs-page` / `docs-nav` / `readme` / `panel-export`). The in-docs links on `sbpp.github.io` are dofollow (Starlight adds no `rel="nofollow"`) and the panel note uses `rel="noopener"` (dofollow, referrer preserved); the root README link is force-`nofollow`'d by GitHub's markdown pipeline (unavoidable), but the UTM tag still attributes the click. Add the same tag to any new outbound RookHelm link; the internal `/rookhelm/` callouts (homepage / overview / data-export) don't need it since they stay on-site. |
| `src/data/sponsors.json` | Canonical source of truth for the project's funding platforms, sponsor tiers, and sponsor roll. Consumed by `src/components/Sponsors.astro` and (eventually) by the main repo `README.md`'s `<!-- sponsors:start --> ... <!-- sponsors:end -->` injection markers + the panel footer in companion issue #1417. Adding a new platform (Open Collective, Patreon, …) or a new sponsor is a one-line edit here — no component change required. |
| `src/styles/sbpp.css` | Panel-parity overrides — brand orange, zinc neutrals, semantic asides, geometry, focus ring. Mirrors `web/themes/default/css/theme.css` token-for-token. **When the panel's `:root` / `html.dark` blocks change, mirror the change here in the same PR** (AGENTS.md "Keep the docs in sync"). |
| `src/components/ThemeProvider.astro` | Override of Starlight's stock dark-leaning theme provider. Defaults the unset preference to `'auto'` (resolves via `prefers-color-scheme`) to match the panel's `'system'` first-paint default, AND ships a `<noscript><style>` block that re-applies the LIGHT-mode tokens onto `:root[data-theme='dark']` so JS-disabled visitors see light (Starlight 0.30 hardcodes `data-theme="dark"` SSR'd; the panel paints light without JS, so this guard restores parity). The user toggle still wins on subsequent visits via `localStorage['starlight-theme']`. |
| `src/components/Footer.astro` | Override of Starlight's stock per-page footer. Re-renders the stock EditLink + LastUpdated + Pagination + optional Built-with-Starlight kudos (pulled straight from Starlight's `virtual:` namespace so future Starlight upgrades pick up new footer chrome automatically) and appends a small "Support SourceBans++" affordance below them. The topbar already carries a matching heart-icon social link; the footer is the second surface so anyone who reads to the end of a docs page can find the sponsor link without scrolling back to the top. Both surfaces route to the canonical `/sponsor/` landing page (issue #1416), not a single platform URL — adding Open Collective / Patreon later is a data-only change on `src/data/sponsors.json`. |
| `src/components/Sponsors.astro` | Reusable component that renders the funding-platforms list + tier-grouped sponsor roll from `src/data/sponsors.json`. Used on `sponsor.mdx` today; index.mdx (and eventually the panel footer from companion issue #1417) can embed it with `showPlatforms={false}` to reuse just the tier-grouped list. Two props: `showPlatforms` (default `true`) gates the platforms section, `showEmptyHint` (default `true`) gates the "be the first" line when the sponsor roll is empty. |
| `src/components/SocialIcons.astro` | Override of Starlight's stock header social-icon row (GitHub / Discord / sponsor heart). Prepends a persistent "RookHelm ↗" pill CTA linking out to rookhelm.com, then re-implements the stock icon loop inline. It does NOT re-render the stock component via the `virtual:` namespace the way `Footer.astro` does: `import ... from 'virtual:starlight/components/SocialIcons'` inside this override resolves back to the override itself and self-recurses until the build stack blows (`RangeError`). The inline loop mirrors `node_modules/@astrojs/starlight/components/SocialIcons.astro` verbatim (same `config.social` source, same markup, same scoped styles) — re-diff it against upstream on a Starlight bump. Starlight renders SocialIcons in both the desktop header row and the mobile-menu preferences panel, so the pill shows at every viewport (no media-query hide). The pill `href` carries the outbound referral tag (see the `rookhelm.mdx` row); the in-docs detail page is `rookhelm.mdx`. |
| `src/assets/logo.svg` + `public/favicon.svg` | The panel's brand mark, copied verbatim from `web/themes/default/images/favicon.svg`. |
| `src/assets/auto/{install,panel}/` | Auto-captured screenshots from `docs/scripts/capture.mjs`. **These ARE committed** so the screenshot diff lands with the UI change. |
| `scripts/capture.mjs` | Playwright-driven capture script (see [Capturing screenshots](#capturing-screenshots) below). |
Expand Down
5 changes: 5 additions & 0 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,13 @@ export default defineConfig({
// URL so a future Open Collective / Patreon addition is a
// data-only change. See ./src/components/Footer.astro for
// the full rationale.
// - SocialIcons: re-implements the stock icon loop inline. See
// ./src/components/SocialIcons.astro for the build constraint
// that forces the inline copy.
components: {
ThemeProvider: './src/components/ThemeProvider.astro',
Footer: './src/components/Footer.astro',
SocialIcons: './src/components/SocialIcons.astro',
},
head: [
{
Expand Down Expand Up @@ -124,6 +128,7 @@ export default defineConfig({
{ label: 'Quickstart (Docker)', slug: 'getting-started/quickstart-docker' },
],
},
{ label: 'RookHelm', slug: 'rookhelm' },
{
label: 'Setup',
items: [
Expand Down
79 changes: 79 additions & 0 deletions docs/src/components/SocialIcons.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
// Override of Starlight's stock SocialIcons. The stock icon loop is
// re-implemented inline (mirroring
// node_modules/@astrojs/starlight/components/SocialIcons.astro — same
// `config.social` source, markup, and scoped styles) rather than
// re-rendered from `virtual:starlight/components/SocialIcons`: from an
// override of this component that specifier resolves back to THIS file
// and recurses until the build stack overflows (RangeError). Re-diff
// against the stock component on a Starlight upgrade.

import config from 'virtual:starlight/user-config';
import { Icon } from '@astrojs/starlight/components';

const links = config.social || [];
---

<a
class="sbpp-rookhelm-cta"
href="https://rookhelm.com?utm_source=sourcebans-pp&utm_medium=referral&utm_content=docs-nav"
rel="noopener"
>
RookHelm
<span class="sbpp-rookhelm-cta__arrow" aria-hidden="true">↗</span>
</a>

{
links.length > 0 && (
<>
{links.map(({ label, href, icon }) => (
<a {href} rel="me" class="sbpp-social-link sl-flex">
<span class="sr-only">{label}</span>
<Icon name={icon} />
</a>
))}
</>
)
}

<style>
/* Mirrors the stock SocialIcons `a` rule so the icons render
identically to upstream (the stock component's scoped styles
don't apply once we stop rendering it). */
.sbpp-social-link {
color: var(--sl-color-text-accent);
padding: 0.5em;
margin: -0.5em;
}
.sbpp-social-link:hover {
color: var(--sl-color-white);
}

.sbpp-rookhelm-cta {
display: inline-flex;
align-items: center;
gap: 0.3em;
padding: 0.3rem 0.7rem;
border: 1px solid var(--sl-color-accent);
border-radius: 999px;
font-size: var(--sl-text-xs);
font-weight: 600;
line-height: 1;
white-space: nowrap;
color: var(--sl-color-text-accent);
text-decoration: none;
transition:
background-color 150ms ease,
border-color 150ms ease,
color 150ms ease;
}
.sbpp-rookhelm-cta:hover,
.sbpp-rookhelm-cta:focus-visible {
background-color: var(--sl-color-accent-low);
border-color: var(--sl-color-accent);
color: var(--sl-color-text-accent);
}
.sbpp-rookhelm-cta__arrow {
font-size: 0.9em;
}
</style>
6 changes: 6 additions & 0 deletions docs/src/content/docs/configuring/data-export.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ high-sensitivity PII. Use encrypted storage and short-lived
presigned URLs. Don't post the URL anywhere public.
</Aside>

<Aside type="tip" title="Migrating to RookHelm?">
This same bundle is what [RookHelm](/rookhelm/), the commercial hosted
alternative, reads when you migrate. A full export is all you need to
move over.
</Aside>

## Permission

Export is gated on `OWNER` only. There's no delegated flag: the
Expand Down
9 changes: 9 additions & 0 deletions docs/src/content/docs/getting-started/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ gets stood up.
</TabItem>
</Tabs>

<Aside type="tip" title="Prefer not to run any of this?">
All three paths above mean owning a host, a database, and the
upgrade cycle. [RookHelm](/rookhelm/) is a commercial, fully-hosted
alternative that runs the stack for you and ships more moderation
tooling out of the box. It imports your SourceBans++ data, so
switching later never means starting over. Self-hosting SourceBans++
stays free.
</Aside>

## Key concepts

A handful of terms come up over and over in the panel and in this
Expand Down
6 changes: 6 additions & 0 deletions docs/src/content/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ each other:
You install both, point them at the same database, and the rest is
day-to-day moderation work.

:::tip[Prefer a hosted option?]
[RookHelm](/rookhelm/) is a commercial, fully-hosted alternative with
more moderation tooling built in. Self-hosting SourceBans++ stays free
and is never going away.
:::

## Where to start

<CardGrid stagger>
Expand Down
51 changes: 51 additions & 0 deletions docs/src/content/docs/rookhelm.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
title: RookHelm
description: RookHelm is a commercial, fully-hosted alternative to SourceBans++ with more moderation tooling built in. It imports your existing SourceBans++ data.
---

import { LinkCard } from '@astrojs/starlight/components';

SourceBans++ is free and self-hostable, and it stays that way. Running
it yourself means owning a webserver, a database, PHP upgrades, plugin
updates, and whatever moderation tooling you stitch together around it.
If you'd rather not, **[RookHelm](https://rookhelm.com?utm_source=sourcebans-pp&utm_medium=referral&utm_content=docs-page)** is a
commercial, fully-hosted alternative: it runs the whole stack for you
and ships more moderation tooling out of the box.

<LinkCard
title="See what RookHelm offers"
href="https://rookhelm.com?utm_source=sourcebans-pp&utm_medium=referral&utm_content=docs-page"
description="Current feature set, pricing, and access. Their site is the source of truth."
/>

## SourceBans++ or RookHelm?

Both manage bans across Source-engine servers. The difference is who
runs the infrastructure and how much comes built in.

**Stay on SourceBans++** when you want a free, source-available panel
you host and control yourself, and you're happy wiring up extra tooling
as you need it.

**Look at RookHelm** when you'd rather not maintain a server and
database, or you want more moderation features as one hosted product
instead of assembling them yourself.

## Migrating from SourceBans++

RookHelm is built to read a standard SourceBans++ data export, so
trying it doesn't mean starting from scratch.

1. Generate a bundle from the panel's
[Full data export](/configuring/data-export/) (owner-only,
`?p=admin&c=export`).
2. Follow RookHelm's import steps to load it.

See [rookhelm.com](https://rookhelm.com?utm_source=sourcebans-pp&utm_medium=referral&utm_content=docs-page) for the current import
process.

:::note
SourceBans++ stays free for community use and fully self-hostable.
RookHelm is a hosted option for communities that would rather not run
the stack themselves; picking it is never required.
:::
7 changes: 7 additions & 0 deletions web/themes/default/page_admin_export.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@
See the <a href="https://sbpp.github.io/configuring/data-export/" target="_blank" rel="noopener noreferrer">data-export docs</a>
for the wire format and per-mode setup.
</p>
<p class="text-xs text-muted m-0 mt-2" data-testid="admin-export-rookhelm">
Moving to a hosted panel?
<a href="https://rookhelm.com?utm_source=sourcebans-pp&amp;utm_medium=referral&amp;utm_content=panel-export"
target="_blank"
rel="noopener">RookHelm</a>
imports this export directly.
</p>
</div>

<div class="card mb-4" data-testid="admin-export-summary-card">
Expand Down
Loading