/* global React, ReactDOM, TweaksPanel, useTweaks, TweakSection, TweakRadio, TweakToggle, GoblinHead */ const { useState, useEffect, useRef, useCallback } = React; /* ===== external integration config (replace placeholders to go live) ===== */ const WEB3FORMS_KEY = "ee75925c-9368-4791-9f1c-522ead6fe7f1"; // free static-site form backend — web3forms.com const STRIPE_LINKS = { // Stripe Payment Links (one hosted URL per tier — zero backend). // LIVE mode (livemode=true, verified 2026-06-01): Scout $2,950 one-time, // Warband $4,800/mo, Warlord $12,500/mo. These charge real cards. scout: "https://buy.stripe.com/5kQeVeabQ1tg0IH7rN2go03", warband: "https://buy.stripe.com/dRmcN6bfU5JwezxeUf2go04", warlord: "https://buy.stripe.com/14A5kE97MdbY3UT3bx2go05", }; const STRIPE_SCOUT_LINK = STRIPE_LINKS.scout; // back-compat alias used by the Summon form // Prompt Goblin scan backend (DigitalOcean Functions web actions). Tier-1 is the // free no-key hygiene scan; Tier-2 is the email-gated Perplexity citation teaser // (dormant until PERPLEXITY_API_KEY is set on the tier2 function). Helpers below // degrade silently to the scripted demo if these are unreachable. const SCAN_API = { tier1: "https://faas-nyc1-2ef2e6cc.doserverless.co/api/v1/web/fn-d4c19df5-3777-4a5d-9843-92f3ebf1f8e7/scan/tier1", tier2: "https://faas-nyc1-2ef2e6cc.doserverless.co/api/v1/web/fn-d4c19df5-3777-4a5d-9843-92f3ebf1f8e7/scan/tier2", }; // Live Tier-1 hygiene scan. Returns the parsed report, or null to fall back to // the scripted demo (network error, non-200, or unconfigured endpoint). async function runHygieneScan(url) { if (!SCAN_API.tier1 || SCAN_API.tier1.includes("")) return null; try { const r = await fetch(SCAN_API.tier1, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ url }), }); return r.ok ? await r.json() : null; } catch { return null; } } // Email-gated Tier-2 citation teaser. 200 even on the honest no-key path; 429 when // the per-IP+email cap is hit. Returns null on network failure / unconfigured. async function runCitationTeaser({ email, domain, competitor }) { if (!SCAN_API.tier2 || SCAN_API.tier2.includes("")) return null; try { const r = await fetch(SCAN_API.tier2, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, domain, competitor }), }); return await r.json(); } catch { return null; } } // Tier-1 report -> terminal lines lives next to below // (SCAN_PHASES / phaseValues / phaseTone). Every phase resolves to a MEASURED // value from the real report — never a fabricated one. function leadDomain(data) { return String((data && data.domain) || "") .trim() .toLowerCase() .replace(/^https?:\/\//, "") .replace(/^www\./, "") .split("/")[0]; } function identifyLead(data) { const email = String((data && data.email) || "").trim().toLowerCase(); const domain = leadDomain(data); if (!window.posthog || !email) return; const props = { email, domain, company_domain: domain, requested_surface: data.target || data.competitor || "", }; try { window.posthog.identify(email, props); if (domain) window.posthog.group("company", domain, { domain }); if (window.posthog.setPersonProperties) { window.posthog.setPersonProperties(props); } } catch (_) {} } function captureEvent(event, props) { try { window.posthog && window.posthog.capture(event, props || {}); } catch (_) {} } // Fire-and-forget lead capture: PostHog identity/event + Web3Forms. function captureLead(event, data) { const domain = leadDomain(data); identifyLead(data); captureEvent(event, { domain, scan_id: data && data.scan_id, has_email: Boolean(data && data.email), target: data && data.target, competitor: data && data.competitor, }); try { window.posthog && window.posthog.capture("lead_recommendation_context", { domain, scan_id: data && data.scan_id, source_event: event, requested_surface: (data && (data.target || data.competitor)) || "", }); } catch (_) {} if (WEB3FORMS_KEY.indexOf("REPLACE") !== -1) { console.info( "[" + event + "] form backend not configured — captured locally:", data, ); return Promise.resolve(false); } return fetch("https://api.web3forms.com/submit", { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: JSON.stringify({ access_key: WEB3FORMS_KEY, subject: event + " ✦ " + (data.domain || ""), from_name: "promptgoblin.io", ...data, }), }) .then((r) => r.ok) .catch(() => false); } /* ===== hooks ===== */ function useLocalTime() { const [t, setT] = useState(() => new Date()); useEffect(() => { const id = setInterval(() => setT(new Date()), 1000); return () => clearInterval(id); }, []); return t; } function useReveal() { const ref = useRef(null); useEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver( (es) => es.forEach((e) => { if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); } }), { threshold: 0.14 }, ); io.observe(el); return () => io.disconnect(); }, []); return ref; } /* light / dark theme — single source of truth, persisted */ function useTheme() { const [theme, setTheme] = useState(() => { try { return localStorage.getItem("pg-theme") || "dark"; } catch (e) { return "dark"; } }); useEffect(() => { document.body.setAttribute("data-palette", theme === "light" ? "bone" : ""); try { localStorage.setItem("pg-theme", theme); } catch (e) {} }, [theme]); return [theme, setTheme]; } /* ===== cursor ===== */ function Cursor() { const cur = useRef(null), lbl = useRef(null); const [label, setLabel] = useState(""); useEffect(() => { // No custom cursor on touch / coarse-pointer devices — skip the rAF + listeners. if (window.matchMedia && window.matchMedia("(pointer: coarse)").matches) return; let x = innerWidth / 2, y = innerHeight / 2, tx = x, ty = y, raf; const onMove = (e) => { tx = e.clientX; ty = e.clientY; }; const tick = () => { x += (tx - x) * 0.3; y += (ty - y) * 0.3; if (cur.current) cur.current.style.transform = `translate(${x}px,${y}px) translate(-50%,-50%)`; if (lbl.current) lbl.current.style.transform = `translate(${x}px,${y}px) translate(-50%,calc(-50% + 26px))`; raf = requestAnimationFrame(tick); }; tick(); const onOver = (e) => { const el = e.target.closest( "[data-cursor-label], a, button, .wcard, .svc-row, .scard", ); if (el) { cur.current?.classList.add("is-hover"); lbl.current?.classList.add("is-hover"); setLabel( el.getAttribute("data-cursor-label") || (el.matches("a,button") ? "exec" : "open"), ); } else { cur.current?.classList.remove("is-hover"); lbl.current?.classList.remove("is-hover"); setLabel(""); } }; document.addEventListener("mousemove", onMove); document.addEventListener("mouseover", onOver); return () => { cancelAnimationFrame(raf); document.removeEventListener("mousemove", onMove); document.removeEventListener("mouseover", onOver); }; }, []); return ( <>
{label}
); } /* ===== loader ===== */ function Loader() { const [n, setN] = useState(0), [hide, setHide] = useState(false); useEffect(() => { let i = 0; const step = () => { i += Math.random() * 9 + 4; if (i >= 100) { setN(100); setTimeout(() => setHide(true), 340); return; } setN(Math.floor(i)); setTimeout(step, 40 + Math.random() * 50); }; step(); }, []); return (
$ goblin crawl --self
{String(n).padStart(3, "0")} %
indexing
schema valid
v 26.05.28
); } /* ===== HUD ===== */ function HUDTop({ theme, setTheme }) { const t = useLocalTime(); const time = t.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false, timeZone: "America/Chicago", }); return (
Prompt_Goblin™ AI SEO / Chicago
./scan ./work ./services ./pricing ./summon
 VISIBLE AF {time} CHI
); } function HUDBottom({ section, total, name }) { return (
41.88°N · 87.63°W
SECTOR — {String(section).padStart(2, "0")}/{String(total).padStart(2, "0")} {name}
EN_US ↑ top
); } /* ===== HERO ===== */ function Hero() { const ref = useReveal(); const [blink, setBlink] = useState(false); useEffect(() => { const id = setInterval(() => { setBlink(true); setTimeout(() => setBlink(false), 160); }, 4200); return () => clearInterval(id); }, []); return (
promptgoblin — ~/site — zsh — 132×42 ⌥⌘
Core positioning

AI search
visibility &
technical SEO.

Get found by robots.
Stay usable by humans.
A one-goblin shop that makes you Visible AF — we measure who the answer engines actually cite for your category, then ship the schema, crawl, and content fixes (software-engineer-reviewed, never auto-deployed) to close the gap. Days, not quarters.
When an AI names the best in your category — is it you, or your competitor? We measure that gap. Then we close it.
✓ Free scan, no card. Paid work backed by a 100% money-back guarantee.
{`schema fragments: [ "@type": "Org", > **nodes ........ } **crawling graphs** ***(.......) "teh"*, **objects ......... ^animated paypaths^ ............crable AF`}
{`> crawl ok > index ok > cite-ready ✓`}
mascot.exe — online
); } /* ===== SPELLBOOK — the three disciplines (AEO · SEO · Accessibility) ===== */ const SPELLS = [ { ico: "fire", nm: "AEO", lv: "answer-engine visibility", sub: "Get cited inside ChatGPT, Claude, Gemini, Perplexity & AI Overviews." }, { ico: "bolt", nm: "SEO", lv: "technical foundation", sub: "Crawl, index, schema, Core Web Vitals — the base AEO stands on." }, { ico: "ice", nm: "A11Y", lv: "WCAG 2.1 AA + Section 508", sub: "Accessible to people and parseable by machines. Required for gov." }, ]; function Spellbook() { const ref = useReveal(); return (
Visibility Spellbook 3 schools · 1 goblin
{SPELLS.map((s) => (
{s.ico === "fire" && } {s.ico === "ice" && } {s.ico === "bolt" && }
{s.nm}
{s.lv}
{s.sub}
))}
> one stack: get found, stay legible, stay compliant v2
); } /* ===== STATS ===== */ const STATS = [ { v: "5", k: "Answer engines scanned" }, { v: "6", k: "JSON-LD blocks · this site" }, { v: "7", k: "Pipeline nodes · engineer-gated" }, { v: "0", k: "Changes auto-deployed" }, ]; function Stats() { return (
// telemetry this site · dogfooded
{STATS.map((s, i) => (
{s.v} {s.e || ""}
{s.k}
))}
); } /* ===== MARQUEE ===== */ function Marquee() { const words = [ "schema.org", "llms.txt", "crawlability", "structured data", "answer engines", "core web vitals", "entity SEO", "JSON-LD", "RAG-ready", "sitemaps", "Visible AF", ]; const run = ( {words.map((w, i) => ( {w} ))} ); return (
{run} {run} {run}
); } /* ===== INDEX / NOW ===== */ function IndexNow() { const ref = useReveal(); return (
01 index · now $ goblin status
// now
Open taking 3 clients · Q3–Q4 26
Building an llms.txt linter
Crawling my own graph + demo targets
Reading Google QRG, again
Based Logan Square, CHI

I make sites legible

to crawlers and LLMs —

so you show up where

the answer gets written.

Two years deep in technical SEO and the new world of answer engines. I ship schema, fix crawl paths, write the{" "} llms.txt, and harden Core Web Vitals — small, urgent jobs that a big agency would scope into a quarter. I move in days and leave you a test suite.
); } /* Work / case-study section ($ ls ./case_study) + its WORK data removed per owner request (2026-06-02). */ /* ===== SERVICES ===== */ const SVCS = [ { num: "(i)", title: "Technical SEO", lead: "The plumbing: crawl paths, indexation, canonicals, robots, sitemaps — fixed so nothing leaks crawl budget.", items: ["Crawl audits", "Indexation", "Canonicals", "Robots & sitemaps"], }, { num: "(ii)", title: "Schema & structured data", lead: "JSON-LD so crawlers and models parse who you are without guessing. Table-stakes hygiene — necessary, not magic. The citation levers are brand mentions and Bing rank; this clears the way for them.", items: ["JSON-LD", "Entity markup", "FAQ / HowTo", "Rich results"], }, { num: "(iii)", title: "AI / answer-engine SEO", lead: "Get surfaced inside ChatGPT, Perplexity, and AI Overviews — by earning the brand mentions and Bing-rank signals that drive citations, plus the llms.txt/AEO hygiene that lets them through.", items: ["llms.txt", "AEO strategy", "Citation tuning", "RAG-readiness"], }, { num: "(iv)", title: "Core Web Vitals", lead: "Make it fast for humans and bots alike. Green vitals, real-device tested.", items: [ "LCP / CLS / INP", "Asset budgets", "Edge & caching", "Lab + field", ], }, { num: "(v)", title: "Content for robots + humans", lead: "Pages that read well to a person and parse cleanly for a model. Both audiences, one draft.", items: [ "Info architecture", "Heading logic", "Internal links", "Editorial passes", ], }, { num: "(vi)", title: "Accessibility (WCAG + 508)", lead: "Usable by people on assistive tech and legible to crawlers — the same fixes serve both. Automated axe-core audit across real component states (collapsed, open, error) plus a software-engineer pass, since tooling alone catches ~57%. Required for government (Section 508 / ADA Title II); never sold as compliance-by-tool.", items: [ "WCAG 2.1 AA + Section 508", "Stateful axe-core audit", "Engineer-reviewed remediation", "Reviewed fix PRs", ], }, ]; function Services() { const [open, setOpen] = useState(0); return (
03 $ man goblin six services · one goblin
{SVCS.map((s, i) => (
setOpen(open === i ? -1 : i)} data-cursor-label={open === i ? "close" : "open"} >
{s.num}
{s.title .split(" ") .map((w, idx) => idx === 0 ? ( {w} ) : ( {w} ), )}
{s.lead}
    {s.items.map((it) => (
  • {it}
  • ))}
+
))}
); } /* ===== QUOTES → house rules / principles (no fabricated testimonials) ===== */ const QUOTES = [ { q: "Nothing auto-deploys. A software engineer reviews every change.", src: "principle · 01" }, { q: "Flat fee. No credits, no meter, no surprise invoice.", src: "principle · 02" }, { q: "We ship the fixes — not a PDF you implement yourself.", src: "principle · 03" }, { q: "Schema is hygiene. We chase the real levers: mentions + Bing.", src: "principle · 04" }, ]; function Quotes() { return (
04 house rules cat ./principles
{QUOTES.map((x, i) => (
{x.q}
{x.src}
))}
); } /* ===== SCROLLS ===== */ const SCROLLS = [ { num: "N.01", date: "May 2026", read: "8 min", tag: "essay", title: "What llms.txt is, and why your site needs one.", }, { num: "N.02", date: "Apr 2026", read: "5 min", tag: "field note", title: "Schema is hygiene, not a citation lever — what actually gets you cited.", }, { num: "N.03", date: "Mar 2026", read: "11 min", tag: "teardown", title: "How a site gets cited by ChatGPT.", }, ]; function Scrolls() { return (
05 $ cat ./scrolls/*.md field notes
{SCROLLS.map((s) => (
{s.num} {s.tag} · {s.date}

field note · soon
))}
); } /* ===== CONTACT / SUMMON — lead intake + payment-ready (config at top of file) ===== */ function Contact() { const [sending, setSending] = useState(false); const [sent, setSent] = useState(false); const [err, setErr] = useState(""); const submit = async (e) => { e.preventDefault(); setErr(""); const data = Object.fromEntries(new FormData(e.target).entries()); identifyLead(data); captureEvent("summon_submitted", { domain: leadDomain(data), has_email: Boolean(data.email), target: data.target || "", }); captureEvent("lead_recommendation_context", { domain: leadDomain(data), source_event: "summon_submitted", requested_surface: data.target || "", }); setSending(true); // If the form backend key isn't set yet, capture locally and show success (demo mode). if (WEB3FORMS_KEY.indexOf("REPLACE") !== -1) { console.info( "[summon] form backend not configured — captured locally:", data, ); setSending(false); setSent(true); return; } try { const res = await fetch("https://api.web3forms.com/submit", { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify({ access_key: WEB3FORMS_KEY, subject: "New goblin summon ✦ " + (data.domain || ""), from_name: "promptgoblin.io", ...data, }), }); if (res.ok) setSent(true); else setErr( "A goblin fumbled that send. Try again, or email hi@promptgoblin.io and we'll run it by hand.", ); } catch (_) { setErr( "Couldn't reach the server — check your connection and retry, or email hi@promptgoblin.io.", ); } setSending(false); }; return (
06 $ goblin --summon 3 slots · Q3–Q4 2026
Drop your domain and what you want to get cited for — I'll run a{" "} free visibility scan and send back the gaps. Best for jobs measured in days, not quarters.
No card, no sales call. Paid work carries a{" "} 100% money-back guarantee — full refund if we don't deliver or you're not happy within 14 days.
{!sent ? (
reserve a Scout audit
{err &&
⚠ {err}
}
) : (
summon received — invisibility cloak: BREAKING
A real software engineer replies within a working day with your free scan. Check your inbox (and spam — goblins lurk there too).
)}
$ chat @promptgoblin
$ ls ./elsewhere github ·{" "} x.com ·{" "} substack
$ pwd Chicago, IL · by appt
© Prompt_Goblin™ 2024–2026 · Visible AF Set in Press Start 2P · VT323 · JetBrains Mono
); } /* ===== HOW IT WORKS — self-healing eval-gate motion diagram ===== */ const RM = () => window.matchMedia("(prefers-reduced-motion: reduce)").matches; const ENGINE_PHASES = [ { stage: 0, gate: null, pk: "fix packet · a11y", pkFail: false, rd: "scan → gap found: contrast on .cta (sample)", tick: "ok" }, { stage: 1, gate: "eval", pk: "→ eval gate", pkFail: false, rd: "eval gate · running 201 tests + eval…", tick: "ok" }, { stage: 1, gate: "fail", pk: "RED · regression", pkFail: true, rd: "eval: RED — patch broke 2 tests. bounce back.", tick: "bad" }, { stage: 0, gate: null, pk: "self-heal · re-patch", pkFail: false, rd: "self-heal loop · retrieval re-tries the fix", tick: "ok" }, { stage: 1, gate: "eval", pk: "→ eval gate", pkFail: false, rd: "eval gate · re-running…", tick: "ok" }, { stage: 1, gate: "pass", pk: "PASS", pkFail: false, rd: "eval: PASS · 201 tests + eval green (2026-06-02)", tick: "ok" }, { stage: 2, gate: "pass", pk: "→ engineer review", pkFail: false, rd: "halt · awaiting engineer approval — nothing auto-ships", tick: "ok" }, { stage: 2, gate: "pass", pk: "approved ✓", pkFail: false, rd: "engineer approved → reviewed PR opened on your repo", tick: "ok" }, { stage: 2, gate: "pass", pk: "re-scan → Δ", pkFail: false, rd: "re-run on cadence · measured before/after delta (sample)", tick: "ok" }, ]; function EngineDiagram() { const [p, setP] = useState(0); const wrapRef = useRef(null); const stageRef0 = useRef(null); const stageRef1 = useRef(null); const stageRef2 = useRef(null); const stageRefs = [stageRef0, stageRef1, stageRef2]; const packetRef = useRef(null); const reduced = RM(); useEffect(() => { if (reduced) { setP(6); return; } let alive = true; const io = new IntersectionObserver(([e]) => { if (!e.isIntersecting) return; let i = 0; const tick = () => { if (!alive) return; setP(i % ENGINE_PHASES.length); i++; timer = setTimeout(tick, i % ENGINE_PHASES.length === 0 ? 1700 : 1500); }; let timer = setTimeout(tick, 600); io.disconnect(); cleanup = () => { alive = false; clearTimeout(timer); }; }, { threshold: 0.35 }); let cleanup = () => { alive = false; }; if (wrapRef.current) io.observe(wrapRef.current); return () => { io.disconnect(); cleanup(); }; }, [reduced]); const place = useCallback(() => { const wrap = wrapRef.current, pk = packetRef.current; if (!wrap || !pk) return; const target = stageRefs[ENGINE_PHASES[p].stage].current; if (!target) return; const w = wrap.getBoundingClientRect(), t = target.getBoundingClientRect(); const x = t.left - w.left + t.width / 2 - pk.offsetWidth / 2; const y = t.top - w.top - pk.offsetHeight - 6; pk.style.transform = `translate(${Math.max(2, x)}px, ${Math.max(2, y)}px)`; }, [p]); useEffect(() => { place(); }, [p, place]); useEffect(() => { const r = () => place(); window.addEventListener("resize", r); const t = setTimeout(place, 120); return () => { window.removeEventListener("resize", r); clearTimeout(t); }; }, [place]); const ph = ENGINE_PHASES[p]; const ENGINE_STAGES = [ { num: "01 · diagnose", name: "Find the gap", desc: "RAG pipeline samples engines + audits SEO / a11y, surfaces a scoped fix." }, { num: "02 · eval gate", name: "Prove it passes", desc: "CI/CD eval gate runs the suite. Red on regression → the fix bounces back to self-heal." }, { num: "03 · engineer", name: "An engineer approves", desc: "Every change halts here. A software engineer approves → reviewed PR. Nothing auto-deploys." }, ]; return (
goblin-engine · self-healing · eval-gated sample run
{ENGINE_STAGES.map((s, i) => { const isGate = i === 1; const active = ph.stage === i; const gateState = isGate ? ph.gate : null; return (
{s.num}
{s.name}
{s.desc}
{isGate && gateState === "pass" && ● eval PASS} {isGate && gateState === "fail" && ● eval RED} {isGate && (gateState === "eval" || gateState === null) && ○ idle} {i === 2 && ( engineer-gated )}
{i < 2 &&
}
); })}
{!reduced && (
{ph.pk}
)}
{ph.tick === "bad" ? "⚠" : "▸"} {ph.rd}
active path failed gate → self-heal engineer review gate

▸ One pipeline: diagnose → eval gate → engineer approve. A failed gate bounces the fix back to the self-healing loop; nothing ships until a software engineer approves. SEO + accessibility proven on the gate (2026-06-02); schema scaffolded.

); } function HowItWorks() { const ref = useReveal(); return (
$ goblin engine --explain self-healing · eval-gated · engineer-approved
how it works · the engine under the hood

How we actually move the needle

// automated system · software-engineer judgment · measurable results

Most SEO shops send you a PDF. We run a system.

Under the hood: one automated pipeline that finds gaps across answer-engine visibility, technical SEO, and accessibility — with bounded self-healing loops and an eval gate that proves a fix actually works before any engineer sees it. Then a software engineer reviews every recommended change. Then it ships to your repo or CMS. Then the system re-runs on a schedule and measures the delta.

You see the gap. Then you watch it close.

"RAG pipeline" and "CI/CD eval gate" are the accurate technical names for what runs. We surface them once for credibility, then translate them for everyone else.

The technical name for the system is a self-healing RAG pipeline on a CI/CD eval gate. The plain-language version: an automated system finds the gaps, proves fixes work, a software engineer ships them, and you watch the numbers move.

); } /* ===== LIVE SCAN — goblin@visibility-mesh terminal (ported from handoff, dark+lime) ===== */ let __scanUid = 0; /* monotonic key source — unique across re-runs of the scan loop */ const mkLine = (o) => ({ ...o, id: __scanUid++ }); const scanSleep = (ms) => new Promise((r) => setTimeout(r, ms)); // The real operations Tier-1 performs, narrated as honest phases. Each resolves // to a MEASURED value from the report below — Tier-1 never queries answer engines, // so this path never claims a ChatGPT/Claude/Gemini citation count. const SCAN_PHASES = [ { key: "fetch", label: "fetch surface" }, { key: "robots", label: "read robots.txt" }, { key: "llms", label: "read llms.txt" }, { key: "schema", label: "parse JSON-LD" }, { key: "score", label: "score hygiene" }, ]; // Idle loop: a clearly-labelled SAMPLE of what the FREE hygiene scan measures. // Illustrative only — no real domain queried, no fabricated engine/citation stats. const SAMPLE_LINES = [ { t: "cmd", text: "goblin scan --surface hygiene --sample" }, { t: "info", text: "illustrative sample · no domain queried" }, { t: "phase", k: "fetch surface", v: "71 KB", tone: "ok" }, { t: "phase", k: "read robots.txt", v: "welcomes AI crawlers", tone: "ok" }, { t: "phase", k: "read llms.txt", v: "not found", tone: "warn" }, { t: "phase", k: "parse JSON-LD", v: "2 of 5 entity types", tone: "warn" }, { t: "phase", k: "score hygiene", v: "64 / 100", tone: "warn" }, { t: "sep" }, { t: "issue", sev: "HIGH", text: "missing FAQPage + Product JSON-LD" }, { t: "issue", sev: "MED", text: "no llms.txt — hygiene, not a citation lever" }, { t: "issue", sev: "LOW", text: "2

tags — pick one" }, { t: "sep" }, { t: "ok", text: "goblin.recommend → structured data + crawl welcome mat" }, { t: "sample", text: "↑ illustrative sample — not your site · enter your domain above for a real scan" }, ]; function scanHost(url) { return String(url || "") .trim() .toLowerCase() .replace(/^https?:\/\//, "") .replace(/^www\./, "") .split("/")[0]; } // Resolve each phase to a MEASURED value pulled straight from the real report. function phaseValues(r) { r = r || {}; const cwv = r.coreWebVitalsProxies || {}; const crawl = r.crawlability || {}; const llms = r.llmsTxt || {}; const schema = r.schema || {}; const foundN = (schema.found || []).length; const total = foundN + (schema.missing || []).length; return { fetch: cwv.htmlKilobytes != null ? cwv.htmlKilobytes + " KB" : "ok", robots: !crawl.present ? "not found" : crawl.welcomesAiBots ? "welcomes AI crawlers" : "blocks AI crawlers", llms: llms.present ? (llms.valid ? "found · on-spec" : "found · off-spec") : "not found", schema: foundN + (total ? " of " + total : "") + " entity types", score: (r.hygieneScore != null ? r.hygieneScore : "?") + " / 100", }; } function phaseTone(r, key) { r = r || {}; if (key === "robots") return r.crawlability && r.crawlability.welcomesAiBots ? "ok" : "warn"; if (key === "llms") return r.llmsTxt && r.llmsTxt.present ? "ok" : "warn"; if (key === "schema") return r.schema && (r.schema.missing || []).length === 0 ? "ok" : "warn"; if (key === "score") { const s = r.hygieneScore; return s >= 80 ? "ok" : s >= 50 ? "warn" : "bad"; } return "ok"; } function scoreBand(s) { if (s == null) return { key: "warn", label: "scan complete" }; if (s >= 80) return { key: "ok", label: "healthy" }; if (s >= 50) return { key: "warn", label: "fixable" }; return { key: "bad", label: "cursed" }; } function LiveScan() { const [mode, setMode] = useState("idle"); // idle | scanning | results | error const [lines, setLines] = useState([]); const [pct, setPct] = useState(0); const [scanLabel, setScanLabel] = useState(""); const [steps, setSteps] = useState([]); // visual stepper: per-phase status + measured value const [report, setReport] = useState(null); const [summary, setSummary] = useState(""); const [errorMsg, setErrorMsg] = useState(""); const [email, setEmail] = useState(""); const [target, setTarget] = useState(""); const runRef = useRef(0); const bodyRef = useRef(null); // Idle: loop the SAMPLE reveal. A run token (runRef) cancels it the instant a // real scan starts and makes the loop immune to StrictMode double-invoke, so // terminal lines never double up. useEffect(() => { if (mode !== "idle") return; const run = ++runRef.current; let i = 0; let timer; setLines([]); setPct(0); const tick = () => { if (runRef.current !== run) return; if (i >= SAMPLE_LINES.length) { timer = setTimeout(() => { if (runRef.current !== run) return; setLines([]); setPct(0); i = 0; timer = setTimeout(tick, 900); }, 4200); return; } setLines((p) => [...p, mkLine(SAMPLE_LINES[i])]); setPct(Math.round(((i + 1) / SAMPLE_LINES.length) * 100)); i++; timer = setTimeout(tick, 300 + Math.random() * 220); }; timer = setTimeout(tick, 500); return () => clearTimeout(timer); }, [mode]); const resetToIdle = () => { runRef.current++; setReport(null); setSummary(""); setErrorMsg(""); setTarget(""); setMode("idle"); }; const onScan = async (e) => { e.preventDefault(); const data = Object.fromEntries(new FormData(e.target).entries()); if (data.botcheck) return; // honeypot const domain = (data.domain || "").trim(); const competitor = (data.competitor || "").trim(); const host = scanHost(domain); const scanId = "scan_" + Date.now().toString(36) + "_" + Math.random().toString(36).slice(2, 8); data.scan_id = scanId; captureLead("free_scan_requested", { domain, email: data.email, competitor, scan_id: scanId, }); setEmail(data.email || ""); setTarget(host); const run = ++runRef.current; const alive = () => runRef.current === run; setMode("scanning"); setReport(null); setErrorMsg(""); setSummary(""); setLines([mkLine({ t: "cmd", text: "goblin scan --surface hygiene --domain " + host })]); setPct(8); setSteps(SCAN_PHASES.map((p) => ({ key: p.key, label: p.label, status: "pending", value: null, tone: "ok" }))); // Fire the REAL Tier-1 request immediately, then narrate the genuine // operations (labels only — values come from the real report) while it runs. const respPromise = runHygieneScan(domain); for (let idx = 0; idx < SCAN_PHASES.length; idx++) { if (!alive()) return; setScanLabel(SCAN_PHASES[idx].label); setSteps((prev) => prev.map((s, i) => (i <= idx ? { ...s, status: "active" } : s))); setPct(Math.min(78, 12 + (idx + 1) * 13)); await scanSleep(420 + Math.random() * 160); } if (!alive()) return; setScanLabel("compiling report"); let resp; try { resp = await respPromise; } catch (_) { resp = null; } if (!alive()) return; // Honest failure path — a real submit NEVER falls back to demo theater. if (!resp || !resp.ok || !resp.report) { const why = (resp && resp.error) || "host unreachable or not public"; setLines((p) => [...p, mkLine({ t: "err", text: "scan failed · " + why })]); setErrorMsg(why); setScanLabel(""); setPct(100); setMode("error"); captureEvent("scan_failed", { scan_id: scanId, domain, reason: "tier1_unreachable" }); return; } // Real result — the "aha" moment. Reveal MEASURED phase values one by one. const r = resp.report; const pv = phaseValues(r); setScanLabel(""); try { window.posthog && window.posthog.capture("scan_result_shown", { scan_id: scanId, domain, hygiene_score: r.hygieneScore, findings: (r.findings || []).length, }); } catch (_) {} for (let j = 0; j < SCAN_PHASES.length; j++) { const p = SCAN_PHASES[j]; if (!alive()) return; await scanSleep(240 + Math.random() * 120); if (!alive()) return; const tone = phaseTone(r, p.key); setLines((prev) => [ ...prev, mkLine({ t: "phase", k: p.label, v: pv[p.key], tone }), ]); setSteps((prev) => prev.map((s, i) => (i === j ? { ...s, status: "done", value: pv[p.key], tone } : s)), ); setPct((prev) => Math.min(94, prev + 4)); } if (!alive()) return; setLines((prev) => [...prev, mkLine({ t: "sep" })]); const findings = (r.findings || []).slice(0, 6); for (const f of findings) { if (!alive()) return; await scanSleep(200 + Math.random() * 120); if (!alive()) return; setLines((prev) => [ ...prev, mkLine({ t: "issue", sev: f.severity >= 4 ? "HIGH" : f.severity === 3 ? "MED" : "LOW", text: f.detail || "", }), ]); } if (!findings.length) { setLines((prev) => [ ...prev, mkLine({ t: "ok", text: "no hygiene gaps found — clean surface" }), ]); } if (!alive()) return; await scanSleep(220); setLines((prev) => [ ...prev, mkLine({ t: "sep" }), mkLine({ t: "ok", text: resp.summary || "scan complete" }), ]); setReport(r); setSummary(resp.summary || ""); setPct(100); setMode("results"); // Email-gated Tier-2 citation teaser (honest no-op until a key is set). if (!competitor) { captureEvent("tier2_skipped_no_competitor", { scan_id: scanId, domain }); } else { runCitationTeaser({ email: data.email, domain, competitor }).then((tier2) => { if (!tier2) { captureEvent("tier2_error", { scan_id: scanId, domain, competitor, reason: "network_or_unreachable", }); return; } if (tier2.ok && tier2.configured && tier2.teaser) { const results = tier2.teaser.results || []; captureEvent("tier2_result_shown", { scan_id: scanId, domain, competitor, engine: tier2.teaser.engine || "perplexity", queries: results.length, client_cited_count: results.filter((r2) => r2.clientCited).length, competitor_cited_count: results.filter((r2) => r2.competitorCited).length, }); } else if (tier2.ok && tier2.configured === false) { captureEvent("tier2_no_key", { scan_id: scanId, domain, competitor }); } else if (tier2.retryAfterHours) { captureEvent("tier2_rate_limited", { scan_id: scanId, domain, competitor, retry_after_hours: tier2.retryAfterHours, }); } else { captureEvent("tier2_error", { scan_id: scanId, domain, competitor, status: tier2.error || "unknown", }); } }); } }; useEffect(() => { const el = bodyRef.current; if (el) el.scrollTop = el.scrollHeight; }, [lines.length, mode]); const band = report ? scoreBand(report.hygieneScore) : null; const statusPill = mode === "results" && band ? band.key : mode === "scanning" ? "scanning" : mode === "error" ? "bad" : "cursed"; const statusText = mode === "results" && band ? (band.key === "ok" ? "✓ " : band.key === "warn" ? "⚡ " : "✕ ") + band.label : mode === "scanning" ? "… scanning" : mode === "error" ? "✕ failed" : "✕ cursed"; return (
$ goblin scan --surface hygiene {mode === "results" ? "live · real result" : mode === "scanning" ? "live · scanning your domain" : mode === "error" ? "scan failed" : "sample · enter your domain for a real scan"}
goblin@visibility-mesh — /scan {String(pct).padStart(3, "0")}%
{lines.map((l) => (
{l.t === "cmd" && ( <> $ {l.text} )} {l.t === "info" && ( <> {" "} {l.text} )} {l.t === "kv" && ( <> {" "} {l.k}:{" "} {l.v} )} {l.t === "phase" && ( <> {" "} {l.k} ··· {l.v} )} {l.t === "warn" && ( <> {" "} {l.text} )} {l.t === "err" && ( <> {" "} {l.text} )} {l.t === "issue" && ( <> {l.sev === "HIGH" ? "▲" : "·"} {" "} [{l.sev}]{" "} {l.text} )} {l.t === "ok" && ( <> {" "} {l.text} )} {l.t === "sample" && ( {l.text} )} {l.t === "sep" && ( ──────────────────────────────── )}
))} {mode === "scanning" ? (
{" "} {scanLabel || "scanning"}{" "}
) : (
$
)}
{mode === "results" && report ? ( ) : mode === "error" ? (
$ scan failed
Couldn't complete a real scan of {target}.
{errorMsg}
) : mode === "scanning" ? (
$ scanning {target}
) : (
$ run a free scan
Live, real result: a technical-hygiene scan of your live page — structured data, crawl welcome mat, head tags & Core Web Vitals proxies. Hygiene is table stakes, not a citation guarantee. The full multi-engine citation audit (ChatGPT · Claude · Gemini · Perplexity · AI Overviews) plus SEO & accessibility ships with a paid Scout audit.
  • structured data / JSON-LD entities
  • robots.txt + llms.txt crawl welcome mat
  • title · meta · canonical · OpenGraph
  • Core Web Vitals proxies
)}
visibility status {statusText}
scan id · GBL-{(pct * 73 + 1031).toString(16).toUpperCase()}
); } function ScanStepper({ steps }) { return (
    {steps.map((s) => (
  1. {s.label} {s.value ? ( {s.value} ) : null}
  2. ))}
); } function ScanResult({ report, email, target, band, steps, onReset }) { const found = (report.schema && report.schema.found) || []; const missing = (report.schema && report.schema.missing) || []; const findings = report.findings || []; const highN = findings.filter((f) => f.severity >= 4).length; const medN = findings.filter((f) => f.severity === 3).length; const lowN = findings.filter((f) => f.severity <= 2).length; return (
{steps && steps.length ? : null}
{report.hygieneScore} /100
hygiene · {target}
{highN} high · {medN} medium · {lowN} low
structured data
{found.map((t) => ( ✓ {t} ))} {missing.map((t) => ( ✕ {t} ))} {!found.length && !missing.length && }

{report.disclaimer}

✓ Real hygiene result delivered above. A software engineer (me) will personally review it and email {email || "you"} about the full citation & accessibility audit — no automated report.
see the full Scout audit
); } /* ===== VISIBILITY MESH — agentic graph (ported from handoff, dark+lime) ===== */ const MESH_NODES = [ { id: "intent", x: 2, y: 16, t: "user.intent", v: '"best fleet software"' }, { id: "llm", x: 30, y: 4, t: "llm.query.expand", v: "GPT · Claude · Gemini · Pplx · AIO" }, { id: "rag", x: 28, y: 56, t: "rag.retrieve", v: "k=24 sources" }, { id: "cite", x: 54, y: 34, t: "citation.weave", v: "you vs. 6 competitors" }, { id: "schema", x: 52, y: 74, t: "audit.schema·seo·a11y", v: "12 gaps · 4 a11y" }, { id: "fix", x: 72, y: 16, t: "goblin.recommend", v: "12 ranked fixes" }, { id: "ship", x: 72, y: 62, t: "engineer.review → PR", v: "queued · 3 pending" }, ]; const MESH_EDGES = [ ["intent", "llm"], ["intent", "rag"], ["llm", "cite"], ["rag", "cite"], ["rag", "schema"], ["cite", "fix"], ["schema", "fix"], ["fix", "ship"], ]; const MESH_STEPS = [ [ "01", "Listen to prompt surfaces", "Agents sample real buyer queries across ChatGPT, Claude, Gemini, Perplexity, and Google AI Overviews — not just keyword tools.", ], [ "02", "Retrieve & diff citation graph", "Map who LLMs actually cite for your category, then diff against your domain to expose exactly which sources you're losing to.", ], [ "03", "Audit: schema · SEO · accessibility", "One pass flags missing entities & structured data, technical-SEO leaks, thin content, AND WCAG 2.1 AA / Section 508 gaps — across real rendered component states, not a single snapshot.", ], [ "04", "Goblin recommendation engine", "Each gap becomes a ranked, scoped task with impact, effort, and a paste-ready fix prompt a coding agent can act on.", ], [ "05", "Engineer-reviewed PRs", "A software engineer approves every change before it hits your CMS, schema, or repo. Agentic, but accountable — nothing auto-ships.", ], [ "06", "Loop on cadence — automatically", "The graph re-runs on a schedule and reports the measured before/after delta. Visibility, citations, SEO, and a11y coverage become a tracked KPI, not a vibe.", ], ]; function VisibilityMesh() { const [active, setActive] = useState(0); useEffect(() => { const id = setInterval( () => setActive((i) => (i + 1) % MESH_NODES.length), 1100, ); return () => clearInterval(id); }, []); const activeId = MESH_NODES[active].id; const activeEdge = MESH_EDGES[active % MESH_EDGES.length]; const VB_W = 900, VB_H = 480; const pos = (id) => { const n = MESH_NODES.find((x) => x.id === id); return { x: (n.x / 100) * VB_W + 92, y: (n.y / 100) * VB_H + 30 }; }; return (
$ goblin graph --run langgraph workflow · engineer-gated · sample run
goblin-graph.runtime ⚡ executing · {String(active + 1).padStart(2, "0")} /{" "} {String(MESH_NODES.length).padStart(2, "0")}
{MESH_EDGES.map(([a, b], i) => { const A = pos(a), B = pos(b); const on = activeEdge[0] === a && activeEdge[1] === b; return ( {on && ( )} ); })} {MESH_NODES.map((n) => (
{n.t}
{n.v}
))}
active path idle edge engineer review gate
    {MESH_STEPS.map(([num, t, d]) => (
  1. {num}
    {t}
    {d}
  2. ))}
); } /* ===== PRICING — Scout / Warband / Warlord (Stripe Payment Links) ===== */ const TIERS = [ { key: "scout", name: "Goblin Scout", who: "founders & solo operators", price: "2,950", interval: "one-time", link: STRIPE_LINKS.scout, cta: "Hire a Scout", desc: "A 5-surface visibility audit that ships reviewed fixes — not a PDF. Headlined by your citation-graph diff vs a named competitor.", bullets: [ "Full LLM citation audit · 5 surfaces", "Schema + entity gap report", "Competitor citation diff (top 6)", "Ranked fix queue · scored by impact × effort", "60-min goblin office hour", ], }, { key: "warband", name: "Goblin Warband", who: "scaleups w/ a marketing team", price: "4,800", interval: "/ mo", link: STRIPE_LINKS.warband, cta: "Summon Warband", featured: true, tag: "best value", desc: "The recurring agentic loop. We run the graph and ship the reviewed PRs — you approve.", bullets: [ "Everything in Scout", "Weekly agentic re-runs", "Citation-acquisition campaigns", "Schema + content PRs to your repo / CMS", "Slack w/ a real goblin · <24h SLA", "Live visibility dashboard", ], }, { key: "warlord", name: "Goblin Warlord", who: "agencies, ecomm, multi-brand", price: "12,500", interval: "/ mo", link: STRIPE_LINKS.warlord, cta: "Forge Warlord", desc: "White-label the goblin. Multi-domain, custom graph, dedicated strategist.", bullets: [ "Everything in Warband", "Up to 8 domains / brands", "Custom LangGraph workflows", "Dedicated retrieval mesh", "Quarterly strategy summit", "White-label deliverables", ], }, ]; function Pricing() { const click = (t) => { // Rich checkout-intent event so PostHog can build a revenue-weighted funnel // (free_scan -> scan_result_shown -> summon -> checkout_clicked -> $). try { window.posthog && window.posthog.capture("checkout_clicked", { tier: t.key, tier_name: t.name, price_usd: Number(String(t.price).replace(/[^0-9.]/g, "")) || 0, interval: t.interval, }); } catch (_) {} }; return (
07 $ goblin --pricing flat fee · no credits · no sales call
{TIERS.map((t) => (
{t.tag && {t.tag}}
{t.name}
// {t.who}
${t.price} {t.interval}
{t.desc}
    {t.bullets.map((b) => (
  • {b}
  • ))}
click(t)} > {t.cta}
))}
✓ 100% money-back guarantee{" "} — on the work, not the algorithm. If we don't deliver your audit, or you're not happy with it within 14 days, you get every dollar back. We won't promise a citation number (nobody honestly can) — we guarantee the work and measure the rest straight.
◆ enterprise · multi-region · regulated — on-prem retrieval, custom auth, a goblin embedded in your team. talk to a goblin
); } /* ===== section spy ===== */ function useSectionSpy(ids) { const [active, setActive] = useState(0); useEffect(() => { const els = ids .map((id) => document.querySelector(`[data-screen-label="${id}"]`)) .filter(Boolean); const io = new IntersectionObserver( (es) => es.forEach((e) => { if (e.isIntersecting) { const idx = ids.indexOf(e.target.getAttribute("data-screen-label")); if (idx >= 0) setActive(idx); } }), { threshold: 0.3 }, ); els.forEach((el) => io.observe(el)); return () => io.disconnect(); }, []); return active; } /* ===== tweaks ===== */ const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/ { grain: true, cursor: true, motion: "med", density: "default", displaySize: "md", }; /*EDITMODE-END*/ function TweaksMount() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); useEffect(() => { document.body.setAttribute("data-grain", t.grain ? "on" : "off"); document.body.setAttribute("data-cursor", t.cursor ? "on" : "off"); document.body.setAttribute("data-motion", t.motion); document.body.setAttribute("data-density", t.density); document.body.setAttribute("data-display", t.displaySize || "md"); }, [t]); return ( setTweak("displaySize", v)} /> setTweak("motion", v)} /> setTweak("density", v)} /> setTweak("grain", v)} /> setTweak("cursor", v)} /> ); } /* ===== app ===== */ const SECTIONS = [ { id: "01 Hero", name: "Hero" }, { id: "02 Spellbook", name: "Spellbook" }, { id: "03 HowItWorks", name: "How we move the needle" }, { id: "04 Mesh", name: "Visibility Mesh" }, { id: "05 Scan", name: "Live Scan" }, { id: "06 Stats", name: "Telemetry" }, { id: "07 Marquee", name: "Keywords" }, { id: "08 Index", name: "Index / Now" }, { id: "10 Services", name: "./services" }, { id: "11 Pricing", name: "Pricing" }, { id: "12 Quotes", name: "Word on street" }, { id: "13 Scrolls", name: "./scrolls" }, { id: "14 Contact", name: "Summon" }, ]; function App() { const ids = SECTIONS.map((s) => s.id); const active = useSectionSpy(ids); const [theme, setTheme] = useTheme(); return ( <>
); } ReactDOM.createRoot(document.getElementById("root")).render();