Swazee mark Product (type slug) Tool (chevron-wrench) Experiment (4-point star) Active (filled diamond) Shipped (hollow diamond) Shelved (diamond + slash) External link (↗) Search (angular magnifier) Filter (funnel) Close / Esc (chunky X) Move down (j) Move up (k) Return / Enter
SWAZEENET
VOL. I · NO. 01 · EST. MCMLXXXVII
BROADSIDE 12 active · 2026·05·14
№ 03 · product · TypeScript / Node 20 · 2025—

gapr,
SEO and GEO in one ledger.

A self-hostable, AGPL-licensed alternative to Ahrefs and SEMrush. First-class GEO --- Generative Engine Optimization --- scoring across the major LLMs.

seo geo agpl

gapr is built around the premise that ranking inside an LLM's generated answer matters as much as ranking on a Google SERP. Beyond traditional SEO (crawls, on-page audits, SERP tracking, backlinks, content briefs, keyword difficulty) it fans a tracked prompt out to ChatGPT, Claude, Perplexity, and Gemini, captures the answer + citations, and computes a transparent GEO Presence Score. Every score in the system exposes its factor breakdown via the Score.breakdown JSON column.

ITech scope

IIGEO subsystem

Generative Engine Optimization is a first-class concern, not a bolt-on. The premise of gapr is that ranking inside an LLM-generated answer is now as load-bearing as ranking on a Google SERP; the schema reflects that:

packages/geo and packages/llm route the prompt across OPENAI_CHATGPT, ANTHROPIC_CLAUDE, PERPLEXITY, and GOOGLE_GEMINI in parallel. The GEO Presence Score is citation share + prose share + position + engine coverage + sentiment; the weights are configurable per workspace, the inputs are surfaced verbatim in Score.breakdown, and the engine version ("claude-sonnet-4-6", etc.) is pinned per fetch so a score is reproducible against a specific model snapshot.

IIIWorkspace map

14 packages under apps/* and packages/*, pnpm 9 + Turborepo. The split is by responsibility, not by technology — everything that talks Postgres lives in packages/db, everything that talks an LLM provider lives in packages/llm, and the apps are thin compositions over those.

IVWhy AGPL self-host

The license choice is operational, not ideological. A self-hosted single-tenant index avoids the per-tenant boundary problems that hosted SaaS competitors keep running into — cross-tenant data leakage from a shared crawler, throttle-budget collisions between customers, and the audit-trail tax of storing every customer’s queries in one database. AGPL is the contract that keeps fork-and-host viable: an operator can run gapr on their own infra and modify it freely, but a hosted derivative must publish its modifications. That trade keeps the project oriented toward operators rather than toward a hosted offering it doesn’t plan to build.

Fig. I.
01crawler 02extractor 03GEO scorer 04index 05API 06console
as of 2026-04-26
Fig. II.
TypeScript499264% TSX228329% Markdown4786% CSS571% JavaScript250%
monorepo: apps/ + packages/ · as of 2026-04-26
Fig. III.
apps 4242 58% packages 3033 42%
apps/ + packages/ · as of 2026-04-26

VSurface

Self-hostable means an operator gets everything needed to bring a single-tenant index up in one repo: the Playwright crawler, the on-page extractor, the GEO scorer (which runs LLM-style queries across OPENAI_CHATGPT, ANTHROPIC_CLAUDE, PERPLEXITY, GOOGLE_GEMINI and scores presence in their generated answers), the index, the API, and the operator console. Single-tenant is a deliberate constraint, not a limitation. Per-tenant boundaries are a known source of cross-tenant data leakage and noisy-neighbor throttle collisions in hosted SEO/GEO platforms; the AGPL self-host alternative is to make the operator own their boundary, which is structurally simpler and auditably yours.

VIRoadmap

The shape ahead: more LLM targets pinned to specific snapshot dates (so a GEO score is reproducible against an exact model version, not a moving target like ‘the latest Claude’), expansion of the crawl schedulers to honor robots.txt + per-host Crawl-Delay caps without operator hand-holding, and a small import path for existing Ahrefs / SEMrush keyword exports so operators can backfill rather than re-crawl from scratch. None of this is shippable yet — the scoring rubric is the first thing that needs to be settled, because the rubric determines what every other piece in the pipeline is being asked to optimize for. Ship a wrong rubric and every score in the system carries the same wrong shape.

:/ ESC