Bu sayfa İngilizce. Aşağıdan dilinizi seçin veya çevrilmiş bir kopya için ops@keepgrid.net adresine e-posta gönderin.

Changelog

Last updated: 2026-05-17

Everything we've shipped, in reverse chronological order. Subscribe by RSS (coming soon) or email ops@keepgrid.net to get updates.

v0.85installerprotrustseo

Ops Engine hardening — blueprints, Pro reports, rollback tests, trust assets

  • **Blueprint engine added**: KeepGrid now builds versioned machine-readable ops blueprints for FiveM/RedM, Minecraft, survival, GMod, paid creators, studios, esports, and generic Discord ops with role specs, category specs, document specs, workflow specs, and safety flags
  • **Installer previews now show the blueprint layer**: dry-run plans include the selected blueprint, version, promise, counts, and safety guarantees before execution. Install summaries also record blueprint ID/version, install mode, and skipped categories
  • **Public install logs upgraded**: shareable logs now show non-sensitive blueprint context and preflight checks while continuing to hide guild IDs, snapshots, tokens, and created-object trackers
  • **Rollback coverage deepened**: tests now cover repeat-safe rollback, corrupted rollback data, and partial Discord deletion failures so rollback behavior stays explicit under edge cases
  • **Pro Ops Report added**: Ops Health now returns and renders a report layer with risk level, highlights, priority actions, and next-review guidance instead of only raw findings
  • **Trust and GTM assets shipped**: added install demo, rollback demo, test-server walkthrough docs plus template-only case-study pages for Minecraft SMP, survival/GMod, paid creators, and game studios
  • **Pricing/SEO copy aligned**: pricing and discovery surfaces now emphasize safe label roles, preflight, no Administrator role creation, rollback tracking, and Pro reports without changing the pricing model
  • Release QA: build, typecheck, lint, Jest, browser QA, and production smoke covered pricing, trust docs, and case-study templates before publishing.
v0.84securityinstallerprotrust

Trust moat — install preflight, no-admin roles, vertical Pro scan wording

  • **Installer preflight added to dry-run plans**: install previews now include safety checks for current guild access, selected install mode, skipped categories, role/channel capacity, rollback coverage, docs-only targets, and Discord role-hierarchy warnings before any write runs
  • **Safe-by-default role creation**: Launch OS no longer creates roles with `Administrator` permissions. Staff, VIP, member, tester, and owner-label roles are created with zero guild-wide permissions; access is controlled through channel/category overwrites instead
  • **Install plan now matches advanced mode**: dry-run previews respect `roles-only`, `channels-only`, `docs-only`, and skipped categories so buyers see the real execution scope instead of a full-install preview for every mode
  • **Execution fails closed on capacity risk**: the installer blocks before mutation if the planned roles or channels would exceed Discord server limits, with clear instructions to remove unused items or narrow install scope
  • **Pro scans became vertical-aware**: Ops Health no longer checks every server for RP-only whitelist language. Minecraft, survival/GMod, paid creator, studio, and esports projects now get access-flow findings that match their actual operating model
  • **Trust docs updated**: `/bot-permissions`, `/security`, and `/docs/install-howto` now explain preflight, role hierarchy, rollback coverage, and the no-Administrator-role policy in plain language
  • Release QA: build, typecheck, lint, Jest, browser QA, and production smoke covered the trust docs and installer safety copy before publishing.
v0.83verticalsseoi18ncontent

Non-Roblox expansion — survival, GMod, creator studio and game studio ops

  • **New non-Roblox vertical layer**: KeepGrid now expands beyond FiveM/RedM, Minecraft, creators, esports, and agencies into Survival servers, GMod/DarkRP, creator studios, and game studios while keeping Roblox intentionally out of scope for this release
  • **Product engine support**: the intake, preview API, AI document generation, fallback templates, free tools, regeneration flow, dashboard labels, and Discord installer now understand the new server types and produce vertical-specific docs, roles, channels, and workflow language
  • **New SEO pages**: `/game-server-discord-ops`, `/survival-server-discord-ops`, `/gmod-darkrp-discord-server`, `/creator-studio-discord-ops`, and `/game-studio-discord-community` ship with dedicated metadata, FAQs, buyer-specific pain points, plan recommendations, and prefilled get-started links
  • **Blog cluster extended across current languages**: new article families for survival game server ops, GMod/DarkRP Discord setup, and game studio Discord community operations were added to the English blog and localized blog routes across all current KeepGrid languages
  • **Discovery surfaces updated**: sitemap, static homepage, verticals hub, pricing/tools metadata, `llms.txt`, `llms-full.txt`, and smoke coverage now describe the expanded game-server and studio direction without making pricing more complex
  • **Browser QA**: confirmed the new landing pages render on the local production build and `/get-started?serverType=survival|gmod|studio` preselects the right platform, labels, and preview CTA wording without stale Whitelist Rubric copy
  • Release QA: build, typecheck, lint, Jest, local smoke, and browser QA covered the new vertical pages and get-started funnels before publishing.
v0.82verticalsseoi18ncontent

Discord Ops Engine vertical packs — Minecraft, creators, esports, agency SEO

  • **Positioning expanded without losing focus**: KeepGrid now frames the core product as a Discord Ops Engine while packaging it through buyer-specific verticals: FiveM/RedM RP, Minecraft SMP/RP, paid creator communities, esports teams/clubs, and agency/client work. Roblox was intentionally not added in this release
  • **New vertical routes and funnels**: `/minecraft-smp-discord-setup`, `/paid-creator-discord-community`, and `/esports-team-discord-server` each get dedicated metadata, buyer-specific pain points, FAQs, plan recommendations, and prefilled `/get-started` links. The intake, preview, project creation, regeneration, dashboard labels, tool form, and AI prompts now understand Minecraft, creator, and esports server types
  • **Product engine now matches the packaging**: `src/lib/ops-taxonomy.ts`, `src/lib/generate-ai.ts`, `src/lib/generate-docs.ts`, and `src/lib/discord-installer.ts` now produce vertical-specific ops systems: Minecraft whitelist/claims/grief/donor workflows, creator tier-access/onboarding/offboarding workflows, and esports tryout/scrim/roster/match-day workflows. Template fallback generation now returns all 13 docs for the core RP path too, not 11
  • **SEO discovery layer rebuilt for the new markets**: sitemap, `llms.txt`, `llms-full.txt`, static homepage copy, locale landings, pricing/tools/agency/legal/trust copy, and smoke coverage now include Minecraft, paid creators, esports, gaming clans, and agency use cases without changing the existing pricing model
  • **Blog cluster shipped across current languages**: new article families for Minecraft, paid creator/agency, and esports/gaming-clan intent were added through `minecraft-blog.ts`, `creator-agency-blog.ts`, `esports-blog.ts`, localized blog indexes, PT static blog routes, and all current localized blog routes including zh-CN
  • **Conversion polish on `/get-started`**: the sidebar now lists all 13 promised documents and swaps the first-doc language by vertical (`Whitelist Rubric`, `Tier Access Flow`, `Tryout Rubric`) so creator/esports buyers do not see stale RP-only wording in the preview CTA or document list
  • Release QA: build, typecheck, lint, Jest, local smoke, and browser QA covered the esports get-started funnel and preview API wording before publishing.
v0.81securitybillingseotrust

Full audit ship — revenue gates, hashed sessions, Pro entitlements, trust center honesty

  • **Revenue gates closed across install + Pro surfaces**: `/api/install/start`, callback, plan, execute now require a paid install-capable plan; `/api/checkout` blocks Pro-only `retainer` checkout on unpaid/docs-only projects; `/api/ops-scan`, Fix Buttons, weekly scans, Staff Task Board, and faction auto-onboarding now check shared Pro entitlement logic in `src/lib/entitlements.ts`
  • **Account takeover prevention**: `/api/projects` no longer creates a session for an existing email-only account from public intake. Existing email-only workspaces can be linked through Discord OAuth only when Discord returns a verified matching email; otherwise a fresh Discord user is created without stealing the email
  • **Session storage hardened**: new sessions store only SHA-256 token hashes in the database while keeping a temporary raw-token lookup fallback so existing 30-day sessions survive the migration window
  • **Cost-control fix**: document regeneration is now checkout-gated so unpaid projects cannot repeatedly trigger AI generation by calling `/api/projects/[id]/regenerate` directly
  • **Trust + legal copy synchronized**: Security and Status now disclose the May 16 internal dotfile-artifact incident remediation instead of claiming no incidents; Terms, Privacy, Bot Permissions, dashboard copy, and static homepage copy now consistently use Docs Pack / Launch OS / Bundle / Annual naming and the 14-day unused refund policy
  • **Three exact-match money pages added**: `/fivem-whitelist-discord-setup`, `/qbcore-discord-setup`, and `/esx-discord-setup` target high-intent framework/intake searches with dedicated metadata, FAQ schema through the shared vertical template, plan recommendations, sitemap entries, llms.txt discovery, and smoke coverage
  • **SEO cleanup**: high-intent page metadata no longer duplicates `KeepGrid` in rendered titles, `/fivem-discord-setup` is in the sitemap, `/case-studies` remains noindex until real customer writeups exist, and stale 11-doc residues were updated to 13 docs
  • Release QA: build, typecheck, lint, Prisma validation, dependency audit, local smoke, and post-deploy smoke passed before publishing.
v0.80mobileseostructured-data

Mobile hamburger menu on all 11 static landings + Schema.org Merchant Listings fields

  • **Mobile hamburger menu on all 11 static landings** (was: only on Next.js pages from v0.79). The static homepage `/` and 10 locale landings (`/ru/`, `/de/`, `/pt/`, …) previously hid the desktop nav at <768px without a replacement, and the locale dropdown was hover-only — unreachable on touch. Now: 44×44 hamburger button with 3-line→X morph in `<header>`, opens a slide-down panel with backdrop blur, JS-cloned nav links from desktop nav (so per-locale labels stay in sync), full-width gradient CTA, and a 2-column grid of all 11 locales with current locale highlighted. ESC + backdrop tap + any link click closes the panel. Body scroll locked while open
  • **Google Search Console fixed: Merchant Listings + Product Snippets warnings**. GSC reported the homepage's `SoftwareApplication` schema and `/pricing` + `/agency` `Product` schemas were missing required Merchant Listings fields. Fixed across 11 static landings + 2 Next.js pages: every Offer now declares `availability: "https://schema.org/InStock"`, `hasMerchantReturnPolicy: { applicableCountry: 'Worldwide', merchantReturnDays: 14, returnFees: 'FreeReturn' }` (matches the existing 14-day refund policy), `shippingDetails: { shippingRate: $0, deliveryTime: 0 days, worldwide }` (digital product, instant delivery). The parent SoftwareApplication / Product nodes now include `image: "https://www.keepgrid.net/opengraph-image"` (was missing — was the critical issue blocking rich-result eligibility)
  • **Patched via JSON-walking script** so all nested Offers (including the 3 inside locale landings' `Service` + `OfferCatalog` shape) got the same fields without per-file hand-editing
  • **Verified live**: 6 offers on `/` all show `avail=✓ return=✓ ship=✓` via curl + JSON parse; 12 `hasMerchantReturnPolicy` and 12 `shippingDetails` refs on `/pricing` (6 tiers × 2 schema serializations)
  • All 96 unit tests pass. ESLint 0/0. Build clean. Smoke 57/57
v0.79mobilea11ypolishux

Mobile-first polish — hamburger sheet, safe-area, touch states, fluid typography, mobile pricing cards

  • **Mobile site nav** (`SiteHeader`): hamburger button (44×44 tap target) toggles a full-screen `MobileSheet` slide-down with backdrop blur. Inside: 4 large nav rows (52px min-height, active page highlighted), full-width gradient `Generate — Free` CTA, and a 2-column locale picker covering all 11 languages with current locale highlighted. ESC + backdrop tap close it; body scroll locked while open. Was: hidden mid-sized nav, no mobile locale switcher at all (P0)
  • **Safe-area handling for iOS notch / Dynamic Island / gesture bar**: `<meta viewport-fit=cover>` added to all 11 static landings + Next.js `export const viewport: { viewportFit: 'cover' }`. `<header>` now uses `paddingTop: env(safe-area-inset-top)`. New utility classes `.safe-pb` / `.safe-pt` available for any future sticky-bottom CTAs (P0)
  • **Pricing comparison table** (`pricing/page.tsx`): the 5-column wide table on `<md:hidden` got replaced with stacked mobile cards — one card per option with `<dl>` of Cost / Docs / Install / Drift rows. Was: forced horizontal scroll on iPhone SE width (P0)
  • **Touch states across 24 components**: gradient CTAs that had `hover:-translate-y-0.5 transition-transform` now also have `active:scale-[0.98] hover-lift transition-all`. Pair with new globals.css media query `@media (hover: none) { .hover-lift:hover { transform: none } }` so touch devices get scale feedback instead of stuck-up state. 34 sites updated (P1)
  • **Audit form result section** rebuilt for mobile: score-first hero pattern (big 7xl number → grade label → server name → metadata) replaces the desktop 3-col row that pushed the score off-screen on narrow viewports. Desktop layout kept identical via `md:` breakpoint. Score size capped at `text-7xl` instead of growing beyond viewport (P1)
  • **Form input attributes**: audit invite field is now `type="url"` + `autoComplete="url"` (was `type="text"` + `autoComplete="off"`) — iOS shows the URL keyboard with `.com` shortcut + lets browsers autofill recently-used URLs. Cards/forms across audit + pricing + reports got `p-5 sm:p-7` instead of fixed `p-7` so 375px-wide screens don't choke on padding (P1)
  • **Fluid typography**: `text-3xl md:text-4xl` headings on get-started + report pages got an extra `sm:` step → `text-2xl sm:text-3xl md:text-4xl`. Score `text-7xl` capped at `text-6xl sm:text-7xl`. Pricing h1 `text-3xl sm:text-4xl md:text-5xl`. Eyebrow labels at `<640px` step down to `font-size: 11px` and `letter-spacing: 0.10em` (was 12px / 0.12em) for legibility on small screens (P1)
  • **Dialog max-height** (`components/dialog.tsx`): `max-h-[90vh]` on mobile (was `calc(100vh-2rem)` which left tall edit-task dialogs feeling like fullscreen takeover). Padding `p-5 sm:p-6` for tighter mobile fit (P2)
  • **Mobile padding consistency**: hero CTAs / cards / containers across 24 files now use `px-4 sm:px-6` and `py-8 sm:py-12` patterns. iPhone SE (375px) tested — content area 343px instead of 327px previously (P1)
  • **Tier card mobile reflow** (`pricing/page.tsx`): `p-5 sm:p-7` + `text-3xl sm:text-4xl` on price + `text-lg sm:text-xl` on label so the 3 primary cards don't waste vertical space on phones
  • All 96 unit tests pass. ESLint 0/0. Build clean. Smoke 57/57 will verify
v0.77i18nlocalizationcompletion

Localization complete — TR/PL/RO/AR/NL added; /audit now fully translated in 11 languages end-to-end

  • **Added 5 more locales** to the `/audit` stack: Turkish, Polish, Romanian, Arabic, Dutch. Each gets the full 36-key UI translation in `audit-i18n.ts`, the full 12-finding × 3-field translation table in `findings-i18n.ts` (180 new strings), the 5 score-summary tier translations, and the 11-impact `PLAYER_IMPACT_MAP` per locale (55 new strings). Total v0.77 translation work: ~330 strings across 5 locales
  • **Result**: `/audit?lang=<any>` for any of `en/ru/de/es/fr/pt/tr/pl/ro/ar/nl` now returns end-to-end localized output — UI labels, score summary, finding titles, finding descriptions, finding fixes, player-impact lines. The full conversion path on every supported locale lives in the visitor's language
  • **`AuditLangBanner` retired**: with all 10 non-English locales covered, the 'audit form is English-only' alert is no longer applicable. Component now returns `null` (kept as a no-op export so the import in `/audit/page.tsx` stays valid; it's a 1-LOC place to wire a future 'switch language' affordance if we add one)
  • **Why this matters**: a Russian, Turkish, Polish, Romanian, Arabic or Dutch operator visiting `/<locale>/` → clicking the live-audit hero → seeing their score → reading findings + fix plan never falls back to English at any step. The funnel is fully native-language across the entire customer journey from landing to checkout intent
  • **Architecture stays simple**: 1 file edit per locale, no per-locale routing, no SSR per-locale rendering. `runAudit()` stays pure; translation happens at the API boundary based on `body.lang`. Adding the next locale is the same pattern — drop one record into 3 maps
  • All 96 unit tests pass. ESLint 0/0. Build clean
v0.76analyticsexperimentationinfra

Lightweight A/B test infra (`lib/ab.ts`) — deterministic bucketing, exposure events, zero deps

  • **`src/lib/ab.ts`** ships the test rig: `assignVariant(experimentKey, variants, visitorId, opts?)` is a pure FNV-1a-hash bucketer (deterministic for the same key+visitor pair, weighted-split aware). `useVariant(key, variants)` is the React hook that returns the assigned variant + emits a one-shot `experiment_exposed` gtag event per session. `pickVariantVanilla(...)` is the same thing for the static landings' inline `<script>` blocks
  • **Visitor ID is persisted in `localStorage`** (`keepgrid:vid`) — same user → same bucket across sessions. Falls back to per-page-load random ID if storage is blocked (privacy mode); experiment still runs, attribution per visit instead of per visitor
  • **Zero new dependencies**: no LaunchDarkly, no Optimizely, no PostHog. ~150 LOC. The deterministic hash means assignments are reproducible from `(key, visitorId)` — useful for SSR variants, server-side rendered pages, or attribution backfill
  • **8 new unit tests** cover: deterministic same-input output, divergence across visitors, weighted-split distribution at scale (90/10 produces 90/10 ±5%), divergence across experiment keys, edge cases (empty variants throws, mismatched weights throws, all-zero weights falls back to first variant)
  • **Funnel events extended**: `experiment_exposed` fires on first render of any variant; reserve `experiment_converted` for conversion-step wiring (e.g. emit when `audit_completed` happens within an experiment)
  • **To run an experiment**: import `useVariant`, render the matching variant, ship. To stop: delete the call site. Old localStorage assignments become inert. No backend, no admin UI
  • **Why this approach**: until we have real conversion data from v0.66-v0.74, we don't know what to test. This lib makes it cheap to wire 1-2 hypotheses next week without a vendor evaluation
  • All 96 unit tests pass (88 → 96). ESLint 0/0. Build clean
v0.75performanceux

Hero performance polish — CLS-free state swaps, content-visibility on below-fold sections

  • **`min-height: 360px` on `.mockcard`** (320px on mobile): the live-audit card swaps between idle/loading/result states with different intrinsic heights. Without a floor, the page below the hero would jump as states change. Now CLS for the in-hero state machine is 0
  • **`content-visibility: auto` on below-fold sections** (`.rv` review-cards section, `.ba-section` Before/After tree, `.alt-row` alternatives, `.cmp` comparison table): browser skips layout + paint until they're near the viewport. Saves ~200-400ms on initial paint on long pages without changing scroll behaviour. `contain-intrinsic-size: 1px 600px` reserves estimated height so the scrollbar doesn't jump
  • Applied to all 11 landings (EN + 10 locales) via `/tmp/inject_live_audit.py` follow-up patch. Idempotent
  • **Why this matters**: the v0.66 hero added a 7-section landing — Before/After tree alone is ~400px tall with monospace fonts. content-visibility is the cheap perf win for this kind of long-form scroll page
  • All 88 unit tests pass. ESLint 0/0. Build clean
v0.74i18nconversioninteractive

Live-audit hero on all 10 locale landings — paste invite, get localized score, in-place

  • **Live-audit form now lives on every locale landing**: pt/de/es/fr/ru/tr/pl/ro/ar/nl. Each has the same 3-state UX as EN (idle / loading / result) with the form labels, hint, error messages, loading copy, result CTAs, and clean-state finding all rendered in the locale's language
  • **Locale-specific lang code passed to /api/audit**: each landing's inline JS sends `body.lang = '<locale>'`. For pt/de/es/fr/ru, the API returns findings + summary already translated server-side via v0.73's findings-i18n. For tr/pl/ro/ar/nl, findings come back EN (as before) — the wrapping UI is still in their language. Translation for those 5 locales is the next layer of work
  • **RTL support for /ar/**: the `<aside>` carries `dir="rtl"`. CSS layout is symmetric so the live-form, score-row, finding rows all render naturally right-to-left
  • **Result CTAs deep-link with the locale preserved**: 'See full report' goes to `/audit?invite=<code>&lang=<locale>`, 'Generate fix plan' goes to `/get-started?source=hero-audit&lang=<locale>&server=<name>&invite=<code>&score=<n>`. The user never accidentally falls back to EN mid-funnel
  • **Implementation**: `/tmp/inject_live_audit.py` patched all 10 files in one pass — adds shared CSS (~80 lines, identical across locales) + per-locale aside markup with translated strings + per-locale inline JS. Idempotent (skips if `hero-audit-form` already present)
  • **Smoke tests** updated to check each locale renders `hero-audit-form` instead of just 'KeepGrid' brand text — verifies the live-audit form is actually present, not just landing markup
  • All 88 unit tests pass. ESLint 0/0. Build clean
v0.73i18nlocalizationfindings

Localization: DE/ES/FR/PT for /audit + server-side findings i18n (12 findings × 6 locales)

  • **`/audit` UI now in 6 locales** (en/ru/de/es/fr/pt): added 36-key DE/ES/FR/PT records to `audit-i18n.ts`. Form labels, score header, section titles ('What new players feel' translated to 'Was neue Spieler erleben' / 'Qué sienten los nuevos jugadores' / etc), fix-plan items, share + subscribe widgets — all language-native
  • **`PLAYER_IMPACT_MAP`** now has parallel records for de/es/fr/pt (11 finding-IDs × 5 new locales = 55 new translation strings). The amber 'What players feel' block reads natively for every supported language
  • **Server-side findings i18n** (`src/lib/findings-i18n.ts`): full translation table for 12 finding IDs × 6 locales × 3 fields (title/description/fix) — 216 strings total. Plus 5 score-summary tiers × 6 locales = 30 strings
  • **`AuditFinding` extended with `vars` field** to carry dynamic values (inviteChannel name, online/member counts, percentage text, verLevel label) so each translator can format its native-language sentence around them. EN strings retained as the source-of-truth fallback
  • **`/api/audit` accepts `lang` (body or query)**: runs the scoring engine in pure mode (no locale knowledge), then `localizeAuditResult(result, lang)` translates findings + summary at the API boundary. Default still 'en'. The audit-form now passes `lang` from URL ?lang= through to the API
  • **`AuditLangBanner`** dropped DE/ES/FR/PT from its 'form is English-only' alert list — those visitors now see the form in their language. Banner still fires for tr/pl/ro/ar/nl
  • **Why this matters**: previously RU users saw RU UI but EN findings — half-localized. Now `/audit?lang=ru` (and de/es/fr/pt) returns end-to-end localized score + impact + fix
  • **Architecture choice**: keeping `runAudit()` pure and translating at the API boundary means scoring math and i18n are decoupled — adding a new locale is a single file edit, not a rewrite
  • All 88 unit tests pass. ESLint 0/0. Build clean
v0.72redesignconversioninteractive

Live audit inline in hero — paste invite, get score in 5 seconds without leaving the homepage

  • **Hero right-column is now interactive**: paste any public Discord invite into the input → POST /api/audit → real Ops Score, grade, top 3 findings rendered in the same card in 5 seconds. No page navigation, no signup, no bot. The mock card from v0.66 is gone — visitors see actual product output now
  • **Three states managed via inline JS** on the static landing: idle (paste-invite form + 'View a sample report' link for visitors without an invite handy), loading (spinner + 'Reading public invite metadata · scoring 5 categories'), result (server name + score + grade + 3 severity-coded findings + dual CTA: 'See full report' / 'Generate fix plan'). Error state shows a salmon-tinted message inline and keeps the form visible for retry
  • **Result CTAs deep-link with the invite already pasted**: 'See full report' goes to `/audit?invite=<code>` (form pre-fills via the v0.66 query param read), 'Generate fix plan' goes to `/get-started?source=hero-audit&server=<name>&invite=<code>&score=<n>` so the intake form is pre-filled too
  • **Funnel events**: `audit_started` (`source: 'hero'`) on submit, `audit_completed` (`source: 'hero'`, `ops_score`, `grade`, `ms` round-trip latency) on success. Wire to existing gtag with the same `track()` shim
  • **Sample report still accessible**: link in the idle hint ('Don't have an invite handy? View a sample report') routes to `/report/sample` for the friction-free path. v0.66's sample report becomes a fallback, not the only on-landing demo
  • **Why this matters**: the v0.66 mock card was a static screenshot of the product. Now the visitor *runs the product* on the homepage. This is the strongest possible 'show, don't tell' move — at the conversion moment they have lived proof the audit actually delivers in 5 seconds, against their server, before they paste anything in /audit or read pricing
  • Reuses the existing `/api/audit` endpoint which already enforces 10-per-15-min IP rate-limit + Zod input validation + invite-code extraction. No new backend needed
  • All 88 unit tests pass. ESLint 0/0. Build clean. **Roadmap delivery items 100% shipped today (v0.68-v0.72)**
v0.71i18nlocalizationru

Russian localization for /audit form (full UI + player-impact + fix-plan)

  • **`/audit?lang=ru` is now fully Russian**: form labels, hint, button copy, error messages, score header, section titles ('Что чувствуют новые игроки', 'План исправлений от KeepGrid'), fix-plan item labels (channels/categories/verification/server card/pinned workflows/audit log), 'Find issues' counter, OK state, share button, link copied state — all translated. New `src/lib/audit-i18n.ts` holds 36 keys per locale + a `getAuditTranslations(lang)` helper
  • **Player-impact map is also localized**: `PLAYER_IMPACT_MAP` is now `Record<"en" | "ru", Record<findingId, impactLine>>` — all 11 finding-impact lines translated to Russian. The `PlayerImpactBlock` accepts `lang` and looks up the right map
  • **Lang banner update**: `AuditLangBanner` previously fired for all 10 locales saying 'form is English-only'. Now `ru` is excluded from the banner list — Russian visitors arriving from `/ru/` see the form fully in Russian without the banner
  • **Findings themselves still come from the English-only `/api/audit` response** — translating the dynamically-generated finding text/fix is a server-side i18n effort scheduled for after we have data on RU traffic conversion. The wrapping UI is what's localized in this ship
  • Why RU first (not all 10): RU is the largest non-EN segment by intuition, and the 1077-token i18n strings authored in v0.71 are the foundation — adding DE/ES/FR/PT etc later is just adding records to `TRANSLATIONS`
  • All 88 unit tests pass. ESLint 0/0. Build clean
v0.70redesignlandingconversion

Before/After Discord tree on landing — visual proof of what KeepGrid installs

  • **New section on the EN landing**, between hero and AI-objection: side-by-side Discord channel-tree comparison. Left panel ('Before', salmon-tinted) shows the typical messy state — flat #general / #chat / #whitelist-form / #staff-chat with `no rules-gate` / `@everyone reads` / `no routing` warning tags. Right panel ('After', mint-tinted) shows the categorized install — Information, Whitelist, Tickets, Staff with proper sub-channels and `pinned` / `gate` / `staff-only` exp tags
  • Section uses the same monospace + colored-tag visual language as the hero mock card, so the landing reads as one continuous product-demo strip instead of 'here's marketing copy'
  • Mobile breakpoint stacks the two trees vertically with a rotated arrow between them
  • **Why this matters**: the earlier landing had to *describe* what KeepGrid installs. Now visitors *see* it before reading any pricing. Maps directly onto the user's principal-level diagnosis #3 ('show product, don't only explain it')
  • All 88 unit tests pass. ESLint 0/0. Build clean
v0.69conversionuxredesign

Audit results: player-impact + fix-plan-preview blocks (the conversion moment)

  • **`/audit` results page now has two new blocks** between the score header and the findings list — these turn structural findings into the conversion language
  • **'What new players feel'** (amber-bordered): hand-curated `PLAYER_IMPACT_MAP` translates each finding ID into the UX consequence ('No clear landing → New players land in the busiest text channel with no idea where to start'). Renders only the top 4 mapped impacts, not a wall of text. The `description` field already says what's structurally missing; this block says what your players actually experience
  • **'KeepGrid's fix plan preview'** (cyan-bordered): derived from finding categories — if onboarding has issues, lists the channels that would be created; if structure has issues, lists 5 categories + 9 roles + permission matrix; etc. Plus two universal items (pinned workflows + audit log/rollback). Each item is a `+ Label · detail` row in a 2-col grid. 'Nothing changes until you approve' eyebrow on the heading drives the safety message
  • **Why this matters**: previously the audit results jumped straight from score → findings → CTA. The visitor saw what's broken but had to imagine what KeepGrid actually does. Now the path is score → impact → install plan → CTA — the value prop is concrete before the price
  • Both blocks suppress when there are zero findings (graceful no-issues state preserved)
  • All 88 unit tests pass. ESLint 0/0. Build clean
v0.68a11ypolishconversion

Modal a11y wrapper + tools lead-magnet copy + pricing bullets cleanup

  • **`<Dialog>` a11y wrapper** in `src/components/dialog.tsx` — drop-in replacement for the bespoke modal shells used in TaskBoard (NewTaskDialog, EditTaskDialog) and OnboardingTour. Adds `role="dialog"`, `aria-modal="true"`, `aria-labelledby` (pointing at the heading id), ESC-to-close, click-backdrop-to-close, focus trap (Tab/Shift-Tab cycles inside the panel), focus restoration on close (returns focus to whatever was focused when the dialog opened), and body scroll lock. Zero new deps, ~70 LOC. Refactored 3 existing dialogs to use it
  • **Tools page-form lead-magnet** copy refresh: post-generation upsell headline changed from 'What happens to this whitelist rubric next?' to '1 of 13 docs · the rest of the system' eyebrow + 'Your X is one piece. Want the full system?' h2 — direct framing that maps the visitor's free generation to the paid product. The 3-card bridge (Docs / Install / Bundle) was already in place from v0.42; only the headline copy changed. Also dropped the `⧉ Copy` button glyph to plain `Copy`
  • **Pricing feature-list markers** changed from `✓` to subtle em-dash (`—`) bullets in muted-2 color. Trust pills under the 3 primary cards lost their `✓` prefix entirely — the pill chips themselves carry the affirmative semantic. Same change applied to the hero `.trust-row` CSS in static landing (removed the `::before { content: '✓' }` pseudo-element)
  • All 88 unit tests pass. ESLint 0/0. Build clean
v0.67polishdesignconsistency

Strip emoji icons from UI — replace decorative emojis with typographic labels

  • **All decorative emojis removed from live UI** across 23 src/app .tsx files, EN landing, and 10 static locale landings. Affected sites: hero CTAs (the magnifier on 'Run Free Ops Audit'), gear on 'Free Tools', globe on the locale switcher, plus rocket/party/warning/sparkle/wrench/lock/lightning emojis scattered through dashboard, ops-health, install flow, factions panel, task board, install log
  • **Status icons converted to typographic labels**: install progress steps, scan history rows, fix execution results now render compact uppercase `OK` / `FAIL` / `RUN` / `SKIP` in mono font with matching color tokens. Information density unchanged; visual register is cleaner and matches the rest of the typographic system
  • **Empty container artifacts cleaned**: when an emoji-only `<div className="text-3xl">` was stripped, the wrapper itself was removed too — no empty boxes left behind. 9 files cleaned
  • **Onboarding tour** lost its per-step emoji field entirely (interface change). Tour reads cleaner without the emoji-centered hero on each step
  • **Activity feed** counter strings dropped the ✓/✗/↩/☐ prefixes — now reads 'N fixes succeeded · M failed · K reverts · J tasks closed' with color-coded chips carrying semantic weight
  • **Hero CTA copy on EN landing** changed from '🔍 Run Free Ops Audit' to 'Run Free Ops Audit'. Same in inline-JS for the Launching segment
  • **Locale landings (10)**: stripped 4 emojis per file (40 total) — same nav/hero CTA / locale-switcher trigger pattern as EN. Trigger now reads 'PT' / 'DE' / 'AR' instead of '🌐 PT' / '🌐 DE'
  • Historical changelog entries that mention emojis in past UI text are intentionally left as-is — they describe what was, not what is
  • All 88 unit tests pass. ESLint 0/0. Build clean
v0.66redesignconversionanalytics

Hero redesign + sample report + 3-card pricing + funnel events

  • **New homepage hero** (static `public/index.html`): segmented selector at top — *Already running* (default) vs *Launching* — swaps the H1, sub-headline, primary and secondary CTA copy live without reload. Right column now shows a **mock Ops Audit Report card**: server name + score 58/100 (amber) + grade D + three severity-coded findings + an *Install plan preview* block. The visitor sees what the product produces before they paste anything
  • **Trust pills under primary CTA**: 'No message access · Preview before install · One-click rollback' rendered inline on the hero so safety lives at the conversion moment, not buried in /bot-permissions
  • **Hero copy collapsed to one focused message**: 'Find what's breaking your RP Discord. Fix it safely in minutes.' — one H1 + one sub + 2 CTAs. The earlier hero had 4 competing messages (audit, generate, docs, free tools). Sample report (`/report/sample`) is now the friction-free way to evaluate KeepGrid for visitors who don't want to paste their invite yet
  • **`/report/sample` route** rendering full report UI on a fictional FiveM server (Los Santos Ops RP, 1,842 members, score 58/100, 8 findings spanning onboarding/structure/trust/growth). Indexable for SEO ('sample discord audit'), with a sticky 'Sample' banner + dual CTA: *Run on my server* / *Skip audit — generate plan*. Fires `sample_viewed` on mount and `sample_audit_clicked` on CTA click
  • **Pricing collapsed to 3 primary cards**: Free Audit → Launch OS ($49) → Launch OS + Pro ($59 + $19/mo, 'Best value' badge). Trust pills under cards. Docs Pack / Annual / Done-for-you / Agency demoted to compact 'More options' grid below — same info, lower visual weight. Decision is now 3-way, not 7-way
  • **Funnel event tracking**: `track()` extended with 12 new events covering hero CTAs (audit / generate / sample), segment switches, sample report views, audit start/complete/fix-click, checkout cancellation, etc. Already wired into hero (inline JS), audit-form (audit_started / audit_completed / audit_fix_clicked), and sample CTAs. Existing `gtag` integration unchanged — no extra dependency
  • **Honest framing of what we sell**: hero now says 'KeepGrid scores onboarding, structure, permissions and ticket flow. You see the exact install plan before the bot changes anything.' This is the product. Not 'we generate 13 documents'. The defensive 'why pay if AI can generate' panel still lives below as supporting context, not first-screen tension
  • All 88 unit tests pass. ESLint 0/0. Build clean. Smoke test will verify hero + sample + pricing on prod
v0.65bugfixauditsmoke-testsux

Round 4 deep audit (4 parallel agents) + production smoke-test suite

  • **4 parallel deep-audit agents** ran on different angles: business-logic + scoring math, security pen-test, data integrity, UX edge cases. Verdict: scoring math bulletproof, install idempotency solid, AI generation safe, Stripe webhook signature + CSRF + OAuth + bot token handling all correct, no SSRF/injection vectors. 7 actionable bugs found and fixed
  • **`scripts/smoke.sh` production smoke-test suite**: 56 HTTP checks against `https://www.keepgrid.net` covering all Next.js public pages, trust center, vertical landings, 10 tool sub-pages, 11 static locale landings (with redirect-follow for trailing-slash 308s), public report page, sitemap/robots/llms, auth-gated dashboard redirect, and cron auth rejection. Color-coded pass/fail output, exit code 1 on any failure. Run with `bash scripts/smoke.sh` (or `BASE=http://localhost:3000` for local)
  • **JSON.parse safety** (`api/install/status/[installId]/route.ts:25-26`, `install-log/[installId]/page.tsx:41-42`): both endpoints called `JSON.parse(install.progress)` unguarded. Corrupted blobs (rare, but possible after schema migration) would 500 the entire endpoint. Now wrapped in try/catch with safe fallback (empty array / null)
  • **Discord guildId snowflake validation** (`api/install/callback/route.ts`): guildId from OAuth callback was passed straight to DB upsert. Discord snowflakes are 17-20 digit numeric strings; anything else gets rejected with `?error=invalid_guild_id` redirect before touching the bot or DB
  • **Stripe checkout cancel state indicator**: previously `cancel_url` returned the user to a clean `/dashboard/[id]` with no signal that they'd cancelled. Now returns to `?checkout=cancelled`, dashboard renders an amber banner: "Checkout cancelled — no charge. Your project is still here, ready when you are."
  • **Long server name truncate fix** (`dashboard/[id]/page.tsx:104`): `truncate` class needed `max-w-*` on the actual span, not just on the parent `min-w-0` container. Added `max-w-[180px] sm:max-w-[280px] md:max-w-md` so 100+ char server names actually ellipsize on mobile. `title` attribute reveals full name on hover
  • **Report invalid-invite CTA pre-fills the invite code** (`report/[invite]/page.tsx`): when the report page can't fetch a Discord invite (expired/closed server), the CTA now links to `/audit?invite=<code>` instead of bare `/audit`. AuditForm reads `?invite=` query on mount and pre-fills the input — user doesn't have to retype anything to retry
  • **Audit non-issues confirmed in deep pass**: AuditLog cascades cleanly via Project FK (no orphan risk), corporate-IP rate-limit aliasing is architectural not a bug, in-memory rate-limit reset on cold start is acceptable for hourly windows, no schema-version field on scan snapshots is latent (only triggers on schema change), email failures are logged + soft-fail (acceptable for non-transactional weekly reports)
  • All 88 unit tests pass. ESLint 0/0. Build clean. Smoke test will run against this deploy
v0.64bugfixsecurityux

Round 3 audit — Stripe checkout idempotency + robots.txt defense-in-depth

  • **Stripe checkout double-session fix** (`api/checkout/route.ts:71`): rapid double-click on the Upgrade button used to create two `checkout.session` rows in Stripe. The first webhook flipped status to paid; the second did nothing harmful (caught by v0.62's `updateMany` guard) but the user saw two abandoned sessions in their Stripe-hosted history. Added an idempotency key derived from `userId:projectId:plan` — Stripe retains it for 24h (same TTL as the session itself), so retries within a day reuse the existing URL
  • **robots.txt defense-in-depth**: previously only `Allow: /`. Page-level `noindex` metadata covers `/dashboard/*`, `/login`, `/report/[invite]`, `/install-log/*` — but defense-in-depth, robots.txt now also `Disallow:`s `/api/`, `/dashboard/`, `/login`, `/report/`, `/install-log/`. Crawlers see a single signal instead of having to fetch each page first to read meta
  • **Audit non-issues confirmed in round 3**: weekly-scans cron is safe (Project has `onDelete: Cascade` on user → deleted users' projects auto-delete, so the cron query never fetches them), no `as any` / `@ts-ignore` papering over real bugs, install rollback captures created items at start and reverses cleanly on failure, no SSRF/open-redirect surfaces (all redirects use hardcoded `new URL()` base), sitemap + canonical + hreflang + noindex on `/report/[invite]` all correct
  • All 88 unit tests pass. ESLint 0/0. Build clean
v0.63bugfixsecurityux

Round 2 bug audit — email header injection guard, ops-health silent-fail toast

  • **Email header injection guard** (`lib/email.ts`): the weekly re-audit subject lines and weekly Pro report subject lines interpolated `guildName` / `serverName` directly. A Discord server with `\r\n` in its name could inject extra SMTP headers (BCC, replyto, etc) at send-time. Added `safeSubject()` helper that strips control chars (0x00-0x1F + 0x7F), collapses whitespace runs, and truncates to 200 chars. Both subject builders now route through it
  • **ops-health silent-fail toast** (`dashboard/[id]/ops-health.tsx:118,122`): the scan-history fetch and the latest-scan-detail fetch had `.catch(() => {})` blocks that hid network errors. Users with flaky connections saw an empty scan list with no signal that anything went wrong. Now both catches `setError(...)` with a refresh hint
  • **Audit non-issues confirmed**: install-button already disables on `loading`, opengraph-images don't render user input, ops-audit/scan handle 0-member servers + null `features` arrays gracefully, score formulas correctly clamp to [0,100], `clean()` sanitizer in `generate-ai.ts` blocks prompt-injection from server-name/factions/description fields
  • All 88 unit tests pass. ESLint 0/0. Build clean
v0.62bugfixrace-conditiondata-integrity

Functional bug audit — 6 real bugs fixed (Stripe race, task revert, login fallback, retry tx, task pagination, auto-tasks error code)

  • **Stripe webhook race fixed** (`api/webhook/stripe/route.ts`): the previous check-then-write pattern (find → check status → update) could let two concurrent webhook deliveries (Stripe is at-least-once) both pass through and double-write. Replaced with an atomic `updateMany({ where: { id, status: { not: 'paid' } } })` — the SQL engine guarantees only one wins. Reads `result.count > 0` to decide whether to log 'processed' or 'duplicate'
  • **markAllAutoDone partial-failure UI bug fixed** (`task-board.tsx:124-145`): bulk-marking auto-tasks done applied an optimistic update before per-task PATCH calls; if a request failed the UI stayed stuck showing tasks as 'done' while server still had them open. Now snapshots the previous status of every task into a `Map`, tracks failed IDs separately, and reverts only the failed ones — successful tasks stay marked done. Matches the per-task revert pattern already in `moveTask`
  • **Login user-name fallback** (`login/page.tsx:12`): `email.split('@')[0]` would create a user with `name=''` if the email was malformed (e.g. `@example.com` slips past HTML5 validation). Empty names broke downstream UI rendering. Now trims and falls back to `'user'` if local-part is empty or whitespace
  • **Retry-generation transaction fix** (`api/projects/[id]/retry/route.ts`): the previous flow was deleteMany → AI gen (30-60s) → loop of creates. If a create failed mid-loop, the project was left with partial documents AND status=error. AI generation now happens FIRST (slow, no DB writes), then a single `prisma.$transaction([deleteMany, ...creates, status update])` swaps docs atomically
  • **Task list pagination** (`api/tasks/[projectId]/route.ts`): `findMany()` had no `take` limit. At scale a project could load thousands of tasks per board fetch. Capped at 500 (more tasks than any board renders usefully); top-priority/recently-updated win when over
  • **Auto-tasks Prisma error code** (`lib/auto-tasks.ts:90-92`): the upsert race-handler matched `/unique constraint/i` against `e.message`. Brittle — Prisma changes that text across versions and DB drivers. Now checks `e.code === 'P2002'` (Prisma's stable error code for unique-key violations)
  • **Audit non-issues**: Stripe signature validation (correct), CRON_SECRET enforcement (correct), all DB-mutating endpoints verify `getSession()` + `userId` ownership, all user input passes Zod, weekly-reaudits update is already atomic in single `update()` call, Discord OAuth state validated against httpOnly cookie
  • All 88 unit tests pass. ESLint 0/0. Build clean
v0.61bugfixcode-qualitydesign-system

ESLint zero-error pass + token sweep cleanup (Tailwind prefix gaps)

  • **ESLint clean: 6 errors → 0**. (1) `agency/page.tsx:204` unescaped `'` in `What's included` → `&apos;`. (2) `doc-update-reminder.tsx:52` Date.now() during render → captured once via `useState(() => Date.now())` so SSR/CSR agree on `daysSince` and the text doesn't flip mid-session at midnight. (3) `task-board.tsx:257` and `launch-calendar.tsx:104` Date.now() during render → eslint-disabled with comments explaining why hydration-safe (parent client-only mount + `if (!mounted) return null` gate). (4) `onboarding-tour.tsx:87` and `non-english-banner.tsx:35` setState in useEffect → eslint-disabled (intentional pattern for reading external browser state once)
  • **Removed 4 unused `Link` imports** from `install-log/[installId]/page.tsx`, `dashboard/[id]/page.tsx`, `docs/permissions/page.tsx`, `glossary/page.tsx` (left over from earlier refactors)
  • **Removed dead variables** in `src/lib/email.ts` (`prevGrade` was destructured but never rendered — the email shows current grade only) and `src/lib/ops-scan.ts` (`everyoneRole` was found but never used — code paths use per-channel `everyoneOverwrite` instead)
  • **Tailwind prefix sweep round 2**: 169 more arbitrary-color conversions across 38 files for prefixes my v0.60 sweep missed (`border-t/r/b/l`, `from`, `via`, `to`, `placeholder`, `divide`, `ring-offset`). Top files: ops-health (5), audit-form (9), task-board (9), install-progress (10), tools/tool-form (11). 1077 total token conversions across v0.60+v0.61
  • **Final state**: 0 ESLint errors, 0 warnings. 88/88 tests pass. Build clean. Remaining 29 arbitrary hex usages are intentional: 23× `via-[#c4faff]` (light-cyan middle stop in 3-color CTA gradients), 3× `#8b5cf6` factions purple (semantically distinct), 3× hex codes inside string literals in this changelog (commentary, not styling)
v0.60refactordesign-systempolish

Mass arbitrary-color → semantic-token sweep (908 conversions, 47 files)

  • **The big one**: 908 instances of arbitrary Tailwind color classes (`text-[#87f3ff]`, `bg-[#0a0d12]`, `border-[#ff9f9a]/30`, etc) converted to semantic tokens (`text-accent`, `bg-bg`, `border-danger/30`). Sweep covered text/bg/border/fill/stroke/ring/outline/decoration/shadow/caret/accent prefixes across all .tsx files in src/app
  • **Token catalog finalized in @theme inline**: bg, surface, panel, line, text, text-secondary, text-tertiary (NEW — was 114 inline hex), muted (now #8a96a8 — was 13 sites at #96a3b4, now matches the dominant 159 sites), muted-2, accent, accent-2, accent-3, warning (NEW — for #fbbf24), danger. Comments inline-document each token's intent + usage count
  • **Why this matters**: changing the accent color (or any other token) is now one CSS edit in globals.css. Previously required grep + replace across 47 files. Tailwind v4's `<token>/<alpha>` modifier (e.g. `bg-accent/8`) works automatically because @theme generates `oklab` color-mix at compile time
  • Files with most edits: `dashboard/[id]/ops-health.tsx` (96), `dashboard/[id]/install/[installId]/install-progress.tsx` (73), `get-started/page.tsx` (71), `tools/tool-form.tsx` (43), `dashboard/[id]/task-board.tsx` (41)
  • Only outlier left: `#8b5cf6` (purple, 3 instances) used for the factions panel badge — kept as arbitrary since semantically distinct from the brand palette
  • All 88 unit tests still pass. Build clean. Visual diff: text-muted shifts from #96a3b4 → #8a96a8 (slightly darker, more neutral) on 13 legacy sites; this aligns with the dominant 159 sites that already used #8a96a8 directly
v0.59polishconsistencybranding

Brand mark parity — bracket logo on Next.js header now matches static landing

  • **Visual continuity fix**: the static marketing landing (/, /pt/, /de/, …) had a bracket-pair SVG logo `[ ]` next to the KeepGrid wordmark — cyan stroke for the left bracket, lilac for the right. The Next.js SiteHeader was wordmark-only — so navigating from `/` to `/audit` lost the brand glyph
  • Added the bracket SVG to both `BrandLink` and `BackLeft` variants of SiteHeader. Same path data, same colors (#87F3FF / #B1A8FF) as the static landing
  • Header brand is now identical glyph + width across all 50+ Next.js pages and the 11 static locale landings
  • All 88 unit tests still pass. Build clean
v0.58refactorpolishdesign-system

Color + brand-gradient token cleanup — second pass on inline-style consolidation

  • **Inline color hex → Tailwind text-* utilities**: 46 instances of `style={{ color: "#87f3ff" }}` (and 5 other brand colors: #b1a8ff, #b8ffcb, #f4f7fb, #ff9f9a, #fff) converted to `text-accent` / `text-accent-2` / `text-accent-3` / `text-text` / `text-danger` / `text-white` utilities. The text-* utilities resolve through @theme inline tokens, so changing the accent color now means one CSS variable edit
  • **Brand gradient utility**: 7 instances of `style={{ background: "linear-gradient(90deg,#87f3ff,#b1a8ff)" }}` consolidated to `.bg-brand-gradient` utility class in globals.css. The Tailwind-native `bg-gradient-to-r from-accent to-accent-2` (37 sites) intentionally left as-is — they already use the design tokens via arbitrary-value syntax
  • Files touched: 13 (tools forms, dashboard ops-health, audit-log, activity-feed, task-board, launch-calendar, onboarding-tour, trust pages)
  • All 88 unit tests still pass. Build clean. No DB migrations
v0.57refactorpolishconsistencydesign-system

Header consistency + design-token consolidation — visual jump fix + eyebrow / heading typography utilities

  • **Header bar now identical width on every page**: SiteHeader had a `maxWidth` prop varying across callers (3xl/4xl/5xl/6xl), so brand mark and CTA shifted horizontally between pages — every navigation looked like a janky reflow. Pinned header bar to `max-w-6xl` always; removed `maxWidth` prop entirely. 25 caller sites updated. Page content still uses its own inner max-width independently
  • Report page had two different SiteHeader widths (3xl on error state, 4xl on success). Both now consistent
  • **Eyebrow utility class family**: 86 instances of `text-xs uppercase tracking-widest font-mono` + `style={{ letterSpacing: "0.12em" }}` consolidated into 5 utility classes (`.eyebrow`, `.eyebrow-tight`, `.eyebrow-wide`, `.eyebrow-tight-wide`, `.eyebrow-sm`). Defined once in globals.css, applied across 27 files
  • **Heading typography tokens**: hero h1/h2 had inline `style={{ lineHeight: 1.05, letterSpacing: "-0.02em" }}` repeated 19 times. Now `tracking-display` (-0.03em), `tracking-headline` (-0.02em), `tracking-title` (-0.01em), `leading-display` (1.05), `leading-headline` (1.1) — registered in @theme inline as Tailwind utilities. Cleanup pass also stripped 13 redundant `tracking-tight` tokens that fought with the new headline tokens
  • **Background + text color token cleanup**: 27 inline `style={{ background: "#0a0d12" }}` (and `+ color: "#f4f7fb"` variants) sites converted to `bg-bg` / `bg-bg text-text` Tailwind utility classes via the @theme inline tokens added in v0.56. 18 redundant `letterSpacing: "0.1em"` inline styles stripped where `tracking-widest` was already in className
  • Result: changing brand colors, eyebrow spacing, or heading typography now means one token edit in globals.css instead of grep-and-replace across 30+ files. The remaining 14 inline `letterSpacing` are legitimately needed (dynamic colors via template literals)
  • All 88 unit tests still pass. Build clean. No DB migrations — pure visual consistency fix
v0.56refactorcode-qualitypolish

Polish/refactor — inline fontFamily styles → Tailwind font-space / font-mono utilities (92% converted)

  • Tailwind v4 @theme inline now registers --font-space + --font-mono pointing at the next/font CSS variables. Result: `font-space` and `font-mono` work as Tailwind utility classes alongside the existing color tokens
  • Bulk-converted ~457 inline `style={{ fontFamily: "var(--font-space)" }}` and `style={{ fontFamily: "var(--font-mono)" }}` usages → `className="... font-space"` / `className="... font-mono"`. 44 files refactored across pages, components, dashboards, modals, blog, docs, glossary, case studies
  • Refactor done via Python AST-aware script that handles 4 cases: alone style, combined style with other keys, no-className element (adds one), existing-className element (appends). Script preserved tag structure + non-fontFamily inline-style keys (lineHeight, letterSpacing, etc.)
  • Final stats: 33 inline fontFamily references remain (mostly dynamic-className expressions where automated merge wasn't safe — left for future hand-conversion). 506 utility-class usages now in the codebase. Maintenance win: changing the brand font in future means 1 token edit instead of 100+ inline-style hunts
  • All 88 unit tests still pass after the refactor. Build clean. No visible rendering changes — Tailwind utilities resolve to the same CSS variables next/font sets
v0.55securitymobilei18nbugfix

3-angle audit batch — security pen-test + mobile UX + i18n correctness

  • **Security P1**: Cron auth no longer falls back to the client-settable `x-vercel-cron` header. CRON_SECRET is now required — both /api/cron/weekly-scans and /api/cron/weekly-reaudits return 503 if the secret isn't set in env. Closes a cost-amplification vector where an attacker could trigger weekly scans by forging the header
  • **Security P2**: Prompt injection defense-in-depth on /api/tools/generate + /api/projects (via lib/generate-ai.ts). The clean() sanitizer now strips backticks, redacts injection-prefix phrases ('ignore prior', 'new instructions', 'system:', closing-tag attempts), and the wrapping XML <server_context> tag stays as the structural barrier
  • **Security non-issues confirmed by audit**: SSRF via Discord invite (Discord URL hard-coded), CSRF on state-changing endpoints (Next.js sameSite=strict), IDOR on projects/scans/audit-logs (consistent userId checks), token leakage in error logs (none found), Stripe webhook signature validation (correct), open redirects on OAuth callback (only redirects to /dashboard or /login)
  • **Mobile P1**: /get-started form was 2-column on ALL widths, cramping inputs to ~45% viewport on iPhone SE. Now single-column on mobile, 2-col at sm+ breakpoint
  • **Mobile P1+P2**: All Pro dashboard modal dialogs (TaskBoard new/edit, Ops-Health Confirm, Onboarding tour) now have max-h-[calc(100vh-2rem)] + overflow-y-auto so tall content actually scrolls instead of clipping the close button on short screens
  • **Mobile P2**: Email + invite + URL inputs across the app got proper inputMode / autoComplete / autoCorrect / autoCapitalize / spellCheck attributes. iOS now shows the email keyboard on email fields (with @-key); Discord invite codes no longer get auto-corrected on Android. Affected: /audit form, /audit subscribe, /get-started server-name + email + Discord-invite, /login email
  • **Mobile P2**: /pricing comparison table minWidth 720px was forcing aggressive horizontal scroll on mobile. Changed to md:min-w-[720px] so it collapses naturally below md breakpoint
  • **i18n P1**: All 10 locale landings (RU/DE/ES/FR/PT/TR/PL/RO/AR/NL) now preserve their lang param when linking to /audit. Was: every locale's 'Free Audit' button dropped users into English with no way back. Now: /audit?lang=XX
  • **i18n P1**: New AuditLangBanner client component on /audit. When ?lang=XX matches a supported locale, shows a small banner: 'Audit form is currently English-only — back to [your locale] homepage'. Translated for all 10 locales, RTL handled for Arabic
  • **i18n P2**: Arabic pivot banner now wraps embedded English fragments (Docs Pack $19, Launch OS + Pro, the 'English →' link text) in <bdi> tags so bidirectional rendering works correctly. Previously: English alphanumerics in RTL context could render in unexpected order on some browsers
  • All 88 unit tests still pass. No DB migrations in v0.55 — all code-level fixes
v0.54a11yperformancebugfix

Perf + a11y audit fixes (5th audit angle) + Stripe indexes + partial-failure cleanup

  • **P1 perf fix**: dashboard 'generating documents' page used <meta http-equiv='refresh' content='4'> which forced full page reloads every 4s — interrupted user interaction, broke devtools, scrolled to top. Replaced with GeneratingPoller client component using router.refresh() at 4s intervals — refetches server-component data without disrupting UI state. Plus aria-live='polite' status announcement for screen readers
  • **P1 a11y fix**: 9 client component files had `focus:outline-none focus:border-accent/40` removing keyboard focus visibility. Bulk-updated to add `focus-visible:outline focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2`. Now keyboard-only users see clear focus rings everywhere they tab. Affected: tools/tool-form, dashboard/audit-log, dashboard/factions-panel, dashboard/launch-calendar, dashboard/doc-update-reminder, dashboard/task-board, audit/audit-form subscribe email
  • **P2 a11y fix**: audit subscribe email field upgraded h-10 → h-12 (Apple HIG 44px+ touch target) + added explicit <label htmlFor> for screen readers (was unlabeled)
  • **P2 a11y fix**: tool-form server-name field gets id + htmlFor + required + aria-required='true'. Optional factions / extra-context fields get aria-required='false' + clearer 'optional' label color (#8a96a8 instead of borderline-fail-contrast #6b7a8d)
  • **P2 fix**: CSV audit-log export now warns on truncation. Adds X-Total-Rows / X-Exported-Rows / X-Export-Truncated headers and prepends a `# WARNING: Export truncated` comment line (Excel + Google Sheets ignore # rows; users see warning in text editor). No more silent data loss for compliance workflows
  • **Performance**: Stripe customer/session lookups were full-scanning the Project table. Added @@index([stripeCustomerId]) + @@index([stripeSessionId]). Migration: 20260429020000_v054_stripe_indexes (additive, safe)
  • **Backend safety**: few-categories + no-staff-channels now per-iteration try/catch + partial-success tracking. If channel 3 of 5 fails (e.g. mid-execution permission loss), the 2 successes are recorded in afterState.created[] with errors[] alongside, and revert can clean them up properly. Previously: failure threw, audit log was 'failed', and the partial successes were orphaned
  • All 88 unit tests still pass. No breaking changes
v0.53bugfixdefensiveux

Bug audit follow-up — closing the P3 longtail (defensive UX, partial-failure cleanup, transaction tightening)

  • /api/projects/[id]/regenerate now hard-fails on malformed JSON instead of silently treating it as an empty body. Empty body still allowed (no fields to update is valid)
  • Bulk fix endpoint: ok=true now requires at least one fix to actually succeed. Previously a request with only non-executable findings returned ok=true with an empty success set
  • Pro Fix Button scan-refresh delay bumped from 1.2s to 2.0s. Discord propagation can lag on busy guilds; smaller delays sometimes showed stale findings post-fix
  • task-board moveTask error handling: 404 = task deleted elsewhere (removes from view), 5xx = revert + show error, network error = revert + 'check connection'. Was a generic 'Failed to move task' for everything
  • tool-form copyResult: clipboard write failures now show inline 'Couldn't copy automatically — select text and Cmd/Ctrl+C' instead of silent failure. Affects insecure-context, Safari permission denial, certain WebViews
  • launch-calendar saveState now distinguishes QuotaExceededError + returns success boolean to callers. Console-warns operator; UI can be extended later to show inline notice
  • install-progress polling: added isMounted guard + AbortController. A poll already in-flight when the component unmounts no longer calls setState (silent React warning + potential stale-state on remount)
  • discordDelete 404 handling: was silently treated as success. Now console-warns when 404 happens (Discord sometimes masks 403 as 404 when bot loses access — distinct cause we want visibility on)
  • All 5 silent-default JSON.parse() blocks in revert handlers now throw with 'audit log {id} corrupted, manual cleanup required' instead of proceeding with empty state (which could revert wrong things)
  • ADMINISTRATOR-bit safeguard: createChannel() now refuses any permission_overwrite that grants the ADMINISTRATOR bit. Defense-in-depth — current fix specs don't grant it, but a future spec misconfig is now caught before reaching Discord
  • Project creation: doc inserts + status flip wrapped in $transaction. Eliminates the partial-state window where some docs saved but status='generating' stuck. The Claude API call stays outside the transaction (would block the connection too long)
  • guildId injected into beforeState/afterState now stripped from PATCH bodies on revert (Discord doesn't accept arbitrary fields on guild PATCH; was previously sent and ignored, but cleaner to strip)
  • All 88 unit tests still pass after these changes. No DB migrations in v0.53 — pure code-level fixes
v0.52bugfixsecurityperformance

Bug audit fixes — 13 bugs across Discord API, auth, Prisma, frontend

  • **P1 fix**: no-rules-gate was sending form_fields as JSON.stringify() — Discord expected an array of objects. The rules gate would render unparseable to end users. Now sends the array directly. Genuine data-corruption bug; severity high but blast radius limited to projects that ran this specific Pro Fix Button (none in production yet)
  • **P1 fix**: too-many-public-write fix used Promise.all() across all text channels in parallel — a guild with 50+ channels would trigger Discord's 50 req/s global rate limit and fail entirely. Replaced with chunked GETs (5 at a time, 100ms breath between batches). Discord-friendly, won't trigger global limit
  • **P1 fix**: revertAuditLog used botInstall.findFirst without sorting, returning whichever install was created first. Multi-install projects could revert against the wrong guild. Now stores guildId in audit log row's beforeState/afterState; revert prefers the recorded guildId, falls back to most-recent install for legacy rows
  • **P1 fix**: discordGet in fix-executor had no 429 retry (unlike ops-scan's discordGet). Inconsistent — fix-executor would throw immediately under high load. Unified retry pattern across both: up to 3 retries honouring retry-after header
  • **P1 fix**: /api/install/callback accepted any guild_id from query string without verifying the bot was actually in that guild. IDOR risk. Now requires fetchGuildInfo() to succeed before creating BotInstall row; returns to dashboard with error if Discord didn't add the bot
  • **P1 fix**: /api/audit/unsubscribe had no rate limit on GET — allowed enumeration of (email, inviteCode) pairs. Added IP-based rate limit: 10 req/hr per IP
  • **P1 fix**: /api/auth/discord and callback had no rate limit. Added: 20/hr for OAuth start, 30/hr for callback per IP
  • **P2 fix**: /api/audit-log accepted unbounded `action` filter — long strings could trigger slow PostgreSQL `contains` LIKE queries. Capped at 100 chars
  • **P2 fix**: CSV export from /api/audit-log allowed offset pagination — could be scripted to dump entire log. Now CSV is single-shot, hard cap 1000 rows, no offset honored
  • **P2 fix**: auto-tasks N+1 + race condition. Added @@unique([projectId, sourceFindingKey]) on Task; refactored syncTasksFromFindings to use upsert + Promise.all (parallelized). Concurrent scans now serialize via the unique constraint instead of producing duplicate auto-tasks
  • **P2 fix**: Audit log queries lacked compound index. Added @@index([projectId, status, createdAt]) so filtered + ordered queries don't full-scan as logs grow. Migration: 20260429010000_v052_indexes_and_constraints
  • **P2 fix**: /api/ops-scan/[scanId] called JSON.parse() on findings/snapshot without try/catch. Corrupted scan data would 500 the entire endpoint. Now wraps in try/catch and returns a clean 'scan data corrupted — please re-run' error
  • **P2 fix**: discord-installer's executeRollback parsed install.created without try/catch — corrupted rollback data would crash. Wrapped with explicit error message pointing to ops@keepgrid.net
  • **P1 fix**: audit-form swallowed JSON.parse errors with generic 'Connection failed' message. Now distinguishes between network errors, 5xx with HTML, and validation errors with specific messages
  • **P1 fix**: /get-started scanDiscord didn't check res.ok — Discord 403/429 errors silently produced empty UI. Now surfaces the error inline
  • **P1 fix**: activity-feed widget used Promise.all which rejects on any single fetch failure — one endpoint down would hide the other. Replaced with safeFetch wrappers that return fallback values per-endpoint. Plus AbortController on unmount
  • **P2 fix**: audit-log filter race condition — rapid filter changes could let an older fetch's response overwrite a newer one. Added AbortController via inFlightRef that aborts the previous load when filters change
  • All 88 unit tests still pass after the changes. Schema migration is additive (no data changes); safe to apply on production
v0.51proadvisoryux

no-icon upgraded to advisory + onboarding tour for Pro subscribers

  • no-icon — upgraded from generic 'cannot auto-set' message to a proper advisory with step-by-step Discord UI walkthrough (Server Settings → Overview → drop file). Specifies image requirements (PNG/JPG/GIF, 512×512 recommended, 8MB max, square aspect). Links to Discord's official customization docs
  • Honest framing: KeepGrid does NOT generate or upload icons on your behalf. Brand identity is owned by your community, not by an AI tool. KeepGrid surfaces the gap; you pick the icon
  • Onboarding tour for new Pro subscribers (v0.50): 3-step modal that fires on the first dashboard visit. Covers dashboard layout, Run All Auto-Fixes feature, and revert. Gated by localStorage so existing users see it once and dismiss. Skip + Back + Next + Done flow with progress dots
  • Total advisory finding coverage: 3 (no-mfa, dead-server, no-icon). Total executable: 10. Total tool generators: 10. Total auto-task auto-creation: 10 finding ids. Total revertible audit-log actions: 10
v0.50proux

Onboarding tour — 3-step Pro subscriber walkthrough

  • (Shipped together with v0.51 in the same release — see v0.51 entry above)
v0.49toolsgrowthseo

4 new free tools — incident-report-template, comp-policy-builder, faction-charter, ban-appeal-flow

  • Tool count goes 6 → 10. Each new tool generates a single-domain ops document tuned to the user's RP style + factions + staff size, with the same lead-magnet flow as the existing 6 (no signup, no card, full preview)
  • incident-report-template — P0–P3 severity matrix, post-mortem framework, internal/public communication templates, 5 FiveM/RedM-specific examples (exploit live, RDM cluster, staff scandal, mass-disconnect, anti-cheat false positive)
  • comp-policy-builder — eligibility table by event type, comp tiers with required approver levels, evidence requirements, anti-abuse rules, approval/denial DM templates, platform-specific currency notes (FiveM ESX/QBCore, RedM dollars+gold)
  • faction-charter — identity/leadership/recruitment/conflict/decay rules. Per-faction subsection if multiple factions provided. RP-style adapted (serious = more lore + formal succession, gang-heavy = tighter conflict rules, semi-serious = lighter)
  • ban-appeal-flow — eligibility per ban type, required form fields, mandatory recusal of original banning staff, decision templates, anti-abuse rules, RP-context examples (VDM cluster, exploit, repeated NVL, staff-conflict)
  • Each tool page is ~1500 words of SEO content (intro, what-the-generator-gives-you, how-to-enforce, anti-patterns, what-this-is-NOT, install bridge to /pricing). Internal cross-links to /glossary, /docs, /blog, related tools
  • /tools index updated to 10 cards. tool-form.tsx TOOL_INSTALL_BRIDGE map extended with 4 new entries. /api/tools/generate Zod enum + TOOL_TO_SPEC dispatch table extended. Sitemap updated with 4 new URLs
v0.48proadvisoryux

Advisory findings — no-mfa + dead-server with action plans (vs disabled 'manual only' placeholder)

  • FixPreview now supports advisory: true mode for findings that genuinely cannot be auto-fixed by a bot — only the guild owner can do them, or they're a content/community problem rather than a config one. Replaces the disabled 'Manual only' button with concrete next-step copy + resource links
  • no-mfa upgraded to advisory: explains that ONLY the guild owner can enable 2FA-required (Discord platform constraint, not a bot limitation). Step-by-step path through Server Settings → Safety Setup. Links to Discord's official 2FA setup guide + KeepGrid's /docs/permissions
  • New dead-server advisory: low active-to-total ratio is a content/community problem, not a config one. Surfaces the 5 most common root causes (RP framework unclear, broken jobs, faction imbalance, slow tickets, onboarding friction). Suggests a 3–5 player survey of recently-inactive members. Links to the 'Why FiveM RP servers fail in month 2' blog + the relaunch playbook in /case-studies/sample
  • Honest copy: 'Don't announce a relaunch — most relaunch announcements are communications fixes for operational/content problems.' Sets expectations rather than overselling what KeepGrid can do
  • UI shows advisory entries with a violet 'Advisory · not auto-executable by design' badge + clickable resource pill list. Distinct from the green 'auto-fix available' badge or the gray 'Manual only' placeholder for as-yet-unsupported fixes
  • All 88 unit tests still pass after the FixPreview type extension. Total executable + advisory finding coverage: 10 executable + 2 advisory = 12 of ~13 typical findings have actionable next steps
v0.47prouxseo

Dashboard polish — activity feed, mark-all-auto-tasks-done, per-page OG images

  • Activity feed widget on Pro dashboard: small &quot;last 7 days&quot; summary above TaskBoard. Counts: ✓ fixes succeeded, ✗ fixes failed, ↩ reverts, ☐ tasks closed. Hidden when there's no 7-day activity (new Pro users see a clean dashboard, not an empty card)
  • &quot;Mark all auto-tasks done&quot; bulk button in TaskBoard header — only appears when 1+ open auto-tasks exist. Confirms before action. Tasks reopen automatically if next scan still detects the underlying finding (auto-task sync behavior unchanged)
  • Per-page Open Graph images for /audit, /pricing, /case-studies. Each emits a unique 1200×630 image via Next.js opengraph-image.tsx pattern with route-specific copy (audit shows 'Score 0–100 in 30 seconds', pricing shows the 3 main tiers, case studies shows 'Format + upcoming stories'). Improves social-share CTR vs the single global OG that was reused everywhere
  • Bonus: dashboard render order is now Project header → Activity feed → TaskBoard → AuditLogPanel → DocViewer, with the activity feed acting as a glanceable status line
v0.46contentseodocs

Content + SEO — /glossary, /docs (4 guides), /blog (3 articles)

  • /glossary — 30 plain-English definitions across 6 categories (Discord, FiveM, RedM, RP, Ops & Workflows, Platform). Covers drift, whitelist rubric, recusal, NVL/RDM/metagaming, ESX/QBCore, txAdmin, ticket SLA, idempotent install, audit log + revert, and more. Each entry has short one-line + long form + related cross-links. Long-tail SEO surface for FiveM/RedM/Discord ops queries
  • /docs — self-serve guide hub with 4 in-depth guides: install-howto (step-by-step from audit to install with common gotchas), whats-pro (plain explainer of Pro tier), permissions (table of every Discord flag KeepGrid uses + when), troubleshooting (8 common issues + diagnostic steps). Shared <DocPage> template for consistency
  • /blog — 3 long-form articles (1500-1900 words each): 'Why FiveM RP servers fail in month 2' (operational decay pattern), 'Whitelist rubric anti-patterns' (6 failure modes + fixes), 'Discord drift — what it is and why it kills RP communities'. Each has TL;DR callout, BlogPosting JSON-LD, internal cross-links to /audit + /tools + /glossary
  • All new pages indexed in sitemap.xml at priority 0.70-0.75. Blog index uses card layout matching case studies; doc index uses 4-card grid; glossary uses category-anchored sections with in-page nav
  • Bonus: /audit + /tools + /pricing + /docs all link to the new content as part of their internal-linking hierarchy. Blog posts link back to /audit and to relevant /tools generators where the article&apos;s topic has a free generator
  • Note: 4 new free tools (incident-report-template, comp-policy-builder, faction-charter, ban-appeal-flow) deferred to v0.47 along with dashboard UX polish — keeps each release focused enough to review
v0.45testsprouxhardening

Quality + hardening — 25 unit tests for fix-executor & fix-permissions, audit log pagination, friendly 403 errors with action steps

  • 25 new unit tests across fix-permissions.test.ts (10 tests) + fix-executor.test.ts (15 tests). Mock fetch + Prisma. Coverage: permission bit math (ADMIN override, owner shortcut, OR-with-everyone), missing-flag reporting, all 7 v0.39 fix specs (success path + idempotent skip), revert paths (guild-PATCH for config flips, channel-DELETE for creates), error handling (403 surfaces as failed audit row), edge cases (already-reverted, unknown id)
  • Audit log pagination: API endpoint accepts ?offset= alongside ?limit= and returns {entries, total, hasMore} for paged responses. CSV export skips count for speed (downloads all matching). UI: Prev/Next buttons appear when total > 50, range indicator shows '1-50 of N'
  • Friendly Discord error messages: 403 → 'Open Server Settings → Roles → KeepGrid in Discord and ensure Manage Channels + Manage Guild are enabled, then retry'. 401 → 'bot token may be invalid, contact ops@keepgrid.net'. 404 → 'guild/channel/role may have been deleted, re-run scan'. 429 → 'rate-limited, wait a minute'. 5xx → 'Discord server error, retry — KeepGrid did not change anything'. Replaces previous 'Discord PATCH /guilds/123 failed: 403 ...' technical message
  • All 4 Discord helpers (GET/PATCH/POST/PUT/DELETE) routed through friendlyDiscordError so the action-oriented copy lands consistently in audit log + UI
v0.44seoi18ntrustux

P1/P2 audit leftovers — homepage AI demote, localized metadata sweep (10 locales), /get-started SSR fallback, audit upsell, ticket SLA precision, tools EN banner

  • Homepage AI framing demoted: 'How it works' step 02 'AI generates 13 documents' → 'KeepGrid builds your server workflows'. 'Built carefully' Claude Sonnet 4 card → 'Workflow generator'. AI mention preserved in a new technical FAQ entry 'What AI does KeepGrid use under the hood?' so the fact stays available, not in the hero
  • Localized metadata sweep across all 10 locales (RU, DE, ES, FR, PT, TR, PL, RO, AR, NL): title + meta description + og:title + og:description + twitter:title + twitter:description rewritten from old '13 documents customized by AI, $49 single payment' to new 'Discord Ops system, 60-120s install, weekly drift control, $19 Docs Pack to $59 + $19/mo Bundle'. Each translated by hand, RTL preserved on Arabic
  • /get-started Suspense fallback replaced with full SEO-friendly server-rendered skeleton: real h1 + sub-headline + 'what you get free' / 'what unlocking gets you' grid + footer link to /pricing + audit. Crawlers and screen readers now see the page intent instead of a bare spinner. Includes a noscript fallback pointing to ops@keepgrid.net for users with JS disabled
  • /audit upsell improvement: new 'After the audit' section explains what the results page actually delivers (4 cards: Score 0–100, severity-ranked findings, player-impact framing, manual-fix-hours estimate) + dedicated CTA 'Run audit → preview fix plan' anchoring back to the form id
  • Trust ticket SLA precision: explicit copy added to Bot Permissions and Security pages — 'Ticket SLA tracking uses ticket/channel metadata only — never reads message bodies'. Lists exact fields used (thread created_at, last_message_id timestamp, category, archived/locked flags). Removes ambiguity for prospects auditing trust pages
  • /tools English-only banner for non-EN visitors: detects navigator.language client-side, shows a translated message + link to the visitor's localized landing for 10 supported locales. Hidden by default for English / unmapped visitors. AR uses dir='rtl'
  • Bonus: /audit form gets id='audit-form' for the new anchor CTA target. Tools page gets <NonEnglishBanner /> client component above the hero
v0.43audittrusti18npricing

Audit response — /pricing page, fix score math, Trust copy + Pro Fix Buttons sync, RU pivot, tools funnel, case studies honesty

  • P0.1 — Built full /pricing page (was 404). 7-tier grid (audit/docs/install/bundle/annual/retainer/agency) + comparison table + 7-question FAQ + Product/FAQPage JSON-LD. Linked to from tools funnel and footer
  • P0.2 — Fixed audit weights math: 40+25+15+15 = 95 was wrong. Added 5th category 'Compliance · 5 pts' (matches the 5 categories actually used in finding generation: onboarding/structure/trust/growth/compliance). Added 'Total: 100 pts' line under the cards
  • P0.3 — Trust copy synced with Fix Buttons reality. Bot Permissions: 'Manage Guild' description now says 'used to read basic guild info during install AND for Pro Fix Buttons (e.g. raise verification level, set description, enable Welcome Screen) — every Fix Button requires explicit click + confirmation modal, never runs in background'. New About Pro Fix Buttons callout box on Bot Permissions. Security page: 'No background writes' bullet expanded to mention Fix Buttons explicitly. Added bullet on the audit-log + revert architecture
  • P0.4 — RU /ru/ pricing block fully replaced with 6-tier model (Docs Pack $19, Bundle $59+$19/mo as best-value, Launch OS $49, Annual $199, Done-for-you $349, Agency $149/mo). Each card has the new feature list + correct CTA href (/get-started?lang=ru&plan=...). Pricing intro replaced with 'Платите за систему, а не за prompt' framing
  • P0.5 — Tools funnel CTAs updated. /tools/[slug] inline upsell paragraphs now link to all three tiers (Docs Pack $19 / Launch OS $49 / Bundle $59+$19/mo) plus /pricing for full plans. /tools index footer card replaced single $49 CTA with 3-card row (Docs / Bundle / Launch OS) — Bundle marked 'Best value' with gradient border
  • P0.6 — Verified CTAs render as real links not text. Done-for-you stays on mailto: with prefilled subject. Agency CTA on homepage redirected to /agency (better than mailto — has the form-style intake). Partners CTA stays on mailto for now
  • P0.7 — Case studies de-faked. /case-studies index headline changed to 'Case study format + upcoming customer stories' with explicit 'no published customer numbers yet' callout. Sample card moved to 'template' visual treatment with amber border + 'View template →' instead of 'Read →'. /case-studies/sample eyebrow/h1/intro now lead with '⚠ Format reference only — not a customer claim'. Quote attribution now reads 'Illustrative quote — not from a real customer'
  • P0.8 — Changelog dates fixed. Future-dated entries (2026-04-30, 2026-05-01) reset to today's actual ship date 2026-04-29. Status page already uses dynamic Date so no change there
  • P1 — Fiverr alt-pricing range aligned: hero comparison row now reads '$30–$300 basic, $200–$800 custom' matching the lower table. Annual KeepClean saving framed concretely ('save $78 vs Launch OS + 12 × Pro = $277'). Agency math clarified — 10 installs are INCLUDED in the $149 base, $29 only applies past the 10. Partner page bundle SKU example aligned to actual prices ($49 install or $59 bundle, not the older $39)
  • Bonus — Sample case study quote attribution + intro now explicitly say it's illustrative. /pricing route added to sitemap-ready URL space
v0.42outreachgrowthprocess

Outreach drafts library — partner / agency / Reddit / press / testimonial

  • /outreach folder added to repo with 7 ready-to-edit templates: hosting-partner-cold, hosting-partner-warm, hosting-partner-followup, agency-cold (DM/LinkedIn variants), reddit-launch (r/FiveM-tuned), press-onepager, customer-testimonial
  • Each template is honest-tone first — leads with the recipient's problem, one clear ask, no 'synergy/leverage' language. Includes editing notes, when-to-use guidance, and what NOT to do
  • press-onepager.md doubles as a partner brief — explains pricing, tech stack, audit-log+revert architecture, and what we explicitly DON'T claim. Update the metrics block with real numbers from your dashboard before sending
  • Reddit launch template is r/FiveM-rules-aware: value-first framing, free audit as the lead (not the paid install), explicit founder transparency. Includes posting-time + mod-relations notes
  • customer-testimonial.md includes 7 question script for the discovery call + anonymization defaults — credible case studies need 'what didn't work' explicitly asked
  • All templates kept in repo (not in docs site) so versioning + git-blame is clean. Founder edits, sends manually — automation deferred until volume justifies it
v0.41proauditcompliance

Audit log filters + CSV export

  • Audit log panel gets filter row: status (all / success / failed / pending / reverted) and free-text action filter ('contains' match on action verb). Re-fetches on filter change
  • 'Export CSV' button downloads up to 1000 entries as RFC 4180 CSV with all columns (id, createdAt, completedAt, status, action, findingId, scanId, target, targetType, userId, errorMessage, canRevert, revertedAt, revertedBy, beforeState, afterState). beforeState/afterState exported as embedded JSON strings — easy to re-parse for compliance review
  • Filename auto-includes projectId-prefix + ISO date so multiple exports don't collide on disk
  • API endpoint extended: /api/audit-log accepts ?status= ?action= ?findingId= ?since= ?format=csv|json — same auth/ownership checks as the JSON endpoint
  • CSV escape implements RFC 4180 quoting (commas/quotes/newlines wrapped in double-quotes with internal-quote doubling). Tested against Excel + Google Sheets parsing
v0.40proauto-fixux

Run All Auto-Fixes — bulk action with per-finding review

  • New '⚡ Run all auto-fixes (N)' button appears at the top of findings list when 2+ executable findings are present. Opens a modal listing each fixable finding with checkbox (default all checked) + severity badge + fix line
  • Single 'I understand' acknowledgement applies to the whole batch. Per-finding execution is sequential server-side (Discord rate-limit-friendly + audit log clarity)
  • Bulk endpoint POST /api/ops-scan/fix/bulk: accepts findingIds[], confirm:'EXECUTE_ALL'. Each fix re-checks permissions individually (different fixes need different bits — MANAGE_GUILD vs MANAGE_CHANNELS) and writes its own audit log row. Failures don't halt the batch — reported per-finding at the end
  • Result view: green ✓ / red ✗ per finding, error message inline for failures, audit log id (truncated) for successes. 'Refreshing scan' notice + auto-rerun of the scan after 1.5s so the dashboard updates
  • Single per-project rate limit (10 fixes/hour) applies — bulk burns N from the quota same as N individual runs. Prevents abuse but lets a fresh Pro user fix everything in one go
  • maxDuration set to 60s to accommodate up to 20 fixes serial (Discord PATCH/POST typically <2s each)
v0.39proauto-fixpermissions

Fix Buttons coverage 7→10 — public-write lockdown + Community Server features

  • too-many-public-write — locks down public-writeable info channels by adding @everyone deny SEND_MESSAGES overwrite. Conservative name regex matches: rules, announcements, news, info, updates, changelog, status, welcome, faq, guides. Skips community channels (general, chat, lounge, off-topic) — those need manual judgment
  • Per-channel before-state captured in afterState.modified[] so revert is precise: if no overwrite existed before, revert DELETEs the one we added; if a prior @everyone overwrite existed, revert PUTs it back exactly
  • no-welcome-screen — enables Discord Welcome Screen and auto-populates up to 4 spotlight channels in priority (#welcome, #rules, #whitelist-apply, #announcements, #general). Fails cleanly with actionable error if the guild isn't yet a Community Server
  • no-rules-gate — enables Membership Screening with a single TERMS field 'I have read and agree to follow the server rules'. Same Community Server precondition + clean error if not enabled
  • Both Community-Server fixes capture full prior config for revert (or revert by disabling if no prior config existed)
  • Total executable findings: 7 → 10. Combined with the Run All bulk action (v0.40) a fresh Pro server can fix ~80% of typical findings in one click
  • New discordPut helper added to the executor toolkit for permission-overwrite endpoints (PUT /channels/{id}/permissions/{overwrite.id}). Returns 204 success, 404 treated as already-gone for revert idempotency
v0.38proauto-fixchannels

Fix Buttons coverage 2→7 — channel creates + handler-based reverts

  • 5 new executable findings: no-rules-channel, no-welcome-channel, no-whitelist-channel, few-categories, no-staff-channels. Total executable: 2 → 7. All non-destructive — they CREATE Discord resources, never delete or modify existing ones
  • no-rules-channel + no-welcome-channel: POST text channel with @everyone read/no-send overwrite (read-only by design). Idempotent — if a channel with the same name already exists, no-op + audit row notes it skipped
  • no-whitelist-channel: POST text channel under an 'Onboarding' category, creating the category if missing. Both creates recorded in afterState.created[] for revert
  • few-categories: ensures 4 standard categories exist (Onboarding, Public, Staff Ops, Faction Channels). Creates only what's missing — never duplicates. Empty before-array means already done
  • no-staff-channels: creates 'Staff Ops' category + #staff-chat / #incidents / #ticket-triage with deny-everyone / allow-staff-role permission overwrites. Discovers the staff role by name (Staff / Moderator / Mod / Admin priority order). Fails cleanly with actionable error if no staff role exists yet
  • Handler-based revert architecture: FixSpec.revert is now an optional custom function. Channel creates revert = DELETE every channel id from afterState.created[] (404 treated as success — already gone). Guild-level fixes still default to PATCHing beforeState back
  • Audit log row's targetType now distinguishes 'guild' vs 'channels' so the revert path knows which API call to make. AuditLog.target points to the created channel id (or guild id for config flips), aiding traceability
  • All 5 new fixes require MANAGE_CHANNELS permission (bit 4). Permission check endpoint returns missing flag names so users can re-grant via Discord Server Settings → Roles → KeepGrid → enable Manage Channels
  • X-Audit-Log-Reason header set on every Discord call (POST/PATCH/DELETE) so server admins see 'KeepGrid fix · create #rules (project xxx)' in their native Discord audit log alongside our internal log
v0.37proauto-fixauditsafety

Fix Buttons execution — audit log + permission scope review

  • Fix Buttons now actually execute on the Discord server. Behind 4 layers of safety: (1) finding-id allow-list (only verification-low + no-description in v0.37), (2) bot-permission scope check before button enabled, (3) explicit checkbox confirmation in modal dialog, (4) server-side re-check of permissions on the execute endpoint
  • New AuditLog DB model captures every mutation: action verb, target id, beforeState (JSON snapshot), afterState (JSON snapshot), status (pending → success | failed | reverted), errorMessage, canRevert flag, timestamps, who-triggered. Indexed by (projectId, createdAt), (projectId, findingId), (projectId, status)
  • lib/fix-executor.ts: handler-per-finding architecture. Each handler captures Discord state via GET, applies the mutation via PATCH with X-Audit-Log-Reason header, captures the after-state from the response. Errors don't swallow — the audit log row keeps status='failed' with the Discord error message so you can see what went wrong
  • lib/fix-permissions.ts: computes the bot's effective permission bits by OR-ing @everyone + assigned roles. Returns missing flag names (e.g. ['MANAGE_GUILD']) so users know which scopes to re-grant. ADMINISTRATOR + guild-owner shortcuts handled. Fully read-only (no Discord state changes)
  • Revert: every successful fix gets a 'Revert' button in the audit log panel. Clicking it re-PATCHes Discord with the captured beforeState, writes a new audit-log row prefixed 'revert_<action>', marks the original status='reverted' linked via revertedBy. Atomic via prisma.$transaction so a half-revert can't corrupt the chain
  • API surface: POST /api/ops-scan/fix (with confirm:'EXECUTE'), POST /api/ops-scan/fix/permissions, GET /api/audit-log?projectId=, POST /api/audit-log/[id]/revert (with confirm:'REVERT'). All authenticated + project-ownership-checked. Rate limit: 10 fix executions per project per hour
  • Dashboard: new <AuditLogPanel> below TaskBoard renders last 50 entries with status badges (pending / success / failed / reverted), expandable JSON before/after diff, error message inline for failed entries, Revert button for revertible successful entries. Empty state explains the system to new Pro users
  • Fix preview block in Ops Health: 'Run fix' button replaces the v0.35 disabled placeholder for whitelisted findings. Shows 'auto-fix available' marker when the finding has executable support. Permission status badge (✓ has perms / ✗ missing flags) displayed inline before Run is enabled
  • Confirmation modal: lists exact steps + 'Not doing' constraints + risk badge + 'I understand' checkbox required before Run becomes clickable. Dismisses after success/failure with the result inline in the preview block
  • Migration: ALTER TABLE adds AuditLog with FK to Project + 3 composite indexes. v0.37 supports 2 finding ids — adding more is a single entry in FIX_SPECS in lib/fix-executor.ts (see verification-low for the template)
v0.36i18ngrowthhonest-signaling

Pivot awareness banner on all 10 localized landings

  • Each of the 10 localized landings (RU, DE, ES, FR, PT, TR, PL, RO, NL, AR) now shows a small banner at the top: '🆕 New plans: Docs Pack $19 · Launch OS + Pro $59 + $19/mo. Currently English only — translation coming.' Each banner rendered in the locale's language
  • Banner deep-links to / (English landing) for visitors who want the new pricing tiers without waiting for full translation. Honest signaling > broken machine-translated pricing
  • AR variant uses dir='rtl' on the banner so the layout reads correctly in Arabic; Cyrillic, Latin, and other LTR locales render natively
  • Existing translated copy below the banner is unchanged — drift control on what already works. Full localized pivot (hero rewrite, 6-card pricing, AI-objection section, comparison table) deferred to professional translators per locale
  • EN landing remains the canonical source of new pricing; locale visitors who don't click the banner still see the prior 3-tier pricing which remains operational
v0.35pagesprogrowthpartners

/agency, /partners, /case-studies + Fix-Preview blocks on Pro dashboard

  • /agency — full landing for the $149/mo + $29/install agency tier. Hero, pricing math (base + per-install + 3–5× client markup), 6 perks (multi-client dashboard, white-label reports, client handoff PDF, etc.), right-fit/wrong-fit lists, 6 FAQs with FAQPage + Product JSON-LD
  • /partners — hosting partner program landing. Targets ZAP, GTXGaming, BisectHosting and similar FiveM/RedM-specialist providers. 30% revenue share, co-branded checkout, ~$3,500+/mo recurring example math at 500 signups × 30% attach. 4-step onboarding flow + 6 FAQs
  • /case-studies — index page with reusable <CaseStudyPage> template (before-after metrics, before/what-changed/quote/result narrative + lessons). One sample case study live at /case-studies/sample (noindex, format reference) showing the structure: 6 hero metrics, operator quote, takeaways. Real customer writeups slot in once available
  • Pro dashboard Fix Preview blocks: each finding card now includes a 'Fix preview' expandable that shows what an automated fix WOULD do — verb-led step list, 'Not doing' explicit non-goals, risk badge (reversible / moderate / high), estimated execution seconds. Mapped for 12 finding IDs (verification-low, no-mfa, rules/welcome/whitelist channels, public-write tightening, etc.)
  • 'Run fix' button intentionally disabled in v0.35 with copy 'Auto-execution is paused while we audit-log every change. For now, apply manually.' Gates execution until Pro v2 ships audit-log + permission-scope review — operators can still read the spec to apply manually
  • lib/fix-preview.ts is the single source of truth for fix specs — extending support is just adding a new entry keyed by finding.id
v0.34protasksautomation

Auto-created Staff Tasks from Ops Health findings

  • Every Pro ops scan (manual + weekly cron) now syncs Staff Tasks from findings: each medium/high/critical finding becomes a Task with priority normal/high/urgent. Severity → priority map: critical=urgent, high=high, medium=normal. Low/info findings stay as scan-only signals (too noisy to push to a board)
  • Dedupe via new Task.sourceFindingKey column (stable string like 'verification-low', 'invite-expires'). Existing manual tasks (sourceFindingKey=null) are NEVER touched by the sync — only auto-tasks are managed automatically
  • Auto-resolve: when a finding disappears from a later scan, the corresponding open Task gets marked done with completedAt set. Pairs with the Wins-this-week panel in v0.32 emails — staff see which auto-tasks closed
  • Regression handling: if a previously-done auto-task's finding reappears in a later scan, the same Task row gets reopened (status=todo, completedAt=null) instead of creating a duplicate. Keeps task history continuous
  • Auto-tasks render with a small cyan 'Auto' badge on the task card alongside the priority badge — title hover explains 'Auto-created from Ops Health, marks itself done when finding is resolved'
  • Sync runs in best-effort try/catch so a task DB issue never fails the underlying scan; errors are logged. Migration: ALTER TABLE Task ADD COLUMN sourceFindingKey + composite index on (projectId, sourceFindingKey)
  • createdBy field gets the literal 'keepgrid-auto' string for these rows (vs userId for manual tasks) — useful for future audit/filter UI
v0.33proretentionui

Before vs Now — lifetime score visualization on Pro dashboard

  • New <BeforeAfterPanel> on the Ops Health card (Pro dashboard) shows lifetime score progression: oldest scan in the loaded window vs the most recent. 3-column layout — Before score + grade + date / delta arrow + points gained or lost / Now score + grade + date
  • Days-between calculated from scan timestamps, surfaced as 'over Nd' under the delta. Window label shows total scans + day-span ('30 scans · ~210d' or '8 scans · ~56d')
  • Color-coded: positive delta in mint, negative in coral, no change in slate. Grade colors carry through to before/after numbers (A=mint, B=cyan, C=violet, D=amber, F=coral)
  • Sparkline (existing <ScoreTrend>) moved out of the latest-score card and into the bottom of the Before/After panel where it makes more sense narratively. Renders only with 3+ scans, so it doesn't appear empty for new Pro subscribers
  • Block sits between the latest-score card and the drift panel — gives Pro subscribers an at-a-glance answer to 'is this working?' which is the question they ask 30 days in. Pairs with v0.32's action-plan email so the trajectory + the work are visible together
v0.32proretentionemail

Weekly Report 2.0 — action-plan email format (vs status report)

  • Weekly Pro report (Mondays 14:00 UTC) reformatted from status-report to action-plan. Subject leads with action count + total time ('3 actions for ServerName this week — ~30 min') instead of just the score. Empty state: 'ServerName is clean this week — Score X/100'
  • Each finding rendered as a numbered, time-boxed action card: severity badge → title → '~N min' time estimate (critical=15, high=10, medium=5, low=2) → 'Do this: [fix]' instructions. Color-coded by severity (critical red, high amber, medium cyan, low mint) so triage is visual
  • Email body header reformatted: 'Do these in order' label above the action list, with totals summary ('3 actions this week · ~30 min total'). Score + delta moved below as supporting context, not the headline
  • New 'Wins this week' panel appears when score went up OR findings were resolved — positive reinforcement so Pro feels like a coach, not just an alert source. Drift summary moved to a smaller secondary block ('Changes since last week')
  • Plain-text version mirrors the new structure: 'DO THESE IN ORDER:' header + numbered actions + Wins line + Changes line. Same time estimates and 'Do this:' framing. Renders cleanly in terminal-style mail clients
  • CTA copy updated from 'Open Ops Health dashboard →' to 'Open dashboard to mark complete →' — primes the action-checklist mental model. (Actual mark-complete UI is still pending P2 work, but the email already nudges that workflow)
v0.31conversionpricingverticals

Vertical-specific plan recommendations on all 8 RP-style landings

  • Each /verticals/* landing now ends with a per-vertical plan recommendation block ('Recommended for [vertical]') above the final CTA. Surface 1–2 plan cards (primary marked 'Best fit', optional alternative) with deep links that pre-select the plan on /get-started
  • Recommendations: Whitelist-only → Docs Pack (alt: Launch OS) — small panels rarely need drift control day-one. Relaunch → Bundle (alt: Done-for-you) — first 60 days decide whether community comes back. PD/EMS → Bundle (alt: Annual) — department-heavy structures drift fastest. RedM → Launch OS (alt: Bundle) — period flavor on top of working ops. Streamer → Bundle (alt: Annual) — one offline mod can torpedo a sponsor. Gang/economy → Bundle (alt: Launch OS) — accountability infrastructure for weekly disputes. Public → Launch OS (alt: Bundle) — onboarding velocity is the metric. Semi-serious → Bundle (alt: Annual) — sweet spot for drift detection
  • Shared <VerticalPage> template extended with optional recommendation prop + internal PLAN_LIBRARY (docs/install/bundle/annual/retainer) so future verticals just pass {primary, alt, headline, reason}. Plan card deep-links use ?plan=<slug>&rpStyle=<style>&source=vertical-<style> for funnel attribution
  • Subtle 'Not sure? Run a free Ops Audit first' link below each recommendation block — re-routes uncertain visitors to the audit-first funnel from v0.30
v0.30growthconversioninfra

Audit funnel: segmented CTAs + free re-audit emails + 3-tier tool bridge

  • Audit form CTAs now segment by score bracket: <50 (critical, push bundle), 50–74 (workable, push install), 75–89 (close, push Pro), 90+ (clean, push weekly accountability). Each bracket has tailored headline + body + primary/secondary CTAs
  • /audit results: new email-capture box for free weekly re-audit (anonymous, no signup). Stores email + invite code in new AuditSubscription DB table (with email/inviteCode unique constraint and unsubscribed flag)
  • New API: POST /api/audit/subscribe (rate-limited 5/15min, validates invite via Discord public API, captures initial score), GET/POST /api/audit/unsubscribe (token-less link with email+invite param)
  • New cron at /api/cron/weekly-reaudits (Mondays 14:30 UTC, after the paid scan cron at 14:00). Fetches AuditSubscription rows, re-runs audit, sends Resend email if score moved ≥5 points OR no email sent in 30 days. Caches per-invite to avoid duplicate Discord API calls
  • New email template renderReAuditEmail: subject reflects score delta direction ('improved 8 points' / 'dropped 3 points' / 'weekly'), body shows current vs prior score, top 3 issues, full report link, install CTA, unsubscribe link
  • Shareable /report/[invite]: new 'Your biggest issue' block above findings — shows the highest-points-deducted finding with player-impact framing ('What your players feel') + 'How KeepGrid fixes it' panel + manual-fix-hours estimate vs 60–120 second auto-fix
  • Tool /tools/[slug] post-generation upsell rewritten as 3-tier bridge (Docs Pack $19 / Bundle $59+$19/mo / Launch OS $49) with per-tool contextual one-liner explaining how the doc maps to installed Discord structure
  • Schema: new AuditSubscription model + paired migration SQL. /api/projects accepts plan field; /get-started reads ?plan= and ?rpStyle= query params from pricing-card and vertical-CTA links
  • Vercel cron config updated with second weekly cron entry
v0.29positioningpricingui

Pivot — pricing v2 + 'pay for the system, not the prompt' positioning (EN)

  • Strategic pivot: AI made document generation cheap. KeepGrid now sells the installed structure + drift control, not the AI text. New positioning: 'Audit your RP Discord. Install the fix. Keep it clean every week.'
  • Hero on EN landing rewritten — 'The Discord Ops System for FiveM & RedM RP servers' label, primary CTA flipped to Run Free Ops Audit (was Generate Free Preview), secondary to 'See My Install Preview'
  • New section right after hero: 'AI can write rules. It cannot safely run your RP Discord.' — directly addresses the cheap-AI objection with side-by-side AI-alone vs AI+KeepGrid comparison
  • Pricing restructured from 3 cards to 6 cards across 2 rows: Docs Pack ($19, NEW), Launch OS ($49, was Auto Install), Launch OS + Pro ($59 today + $19/mo, NEW bundle, marked Best value), Annual KeepClean ($199/yr, NEW), Done-for-you ($349 beta), Agency ($149/mo + $29/install, NEW beta tier)
  • New honest comparison table: ChatGPT direct ($0–$20/mo, manual setup) vs Fiverr freelancer ($30–$300, varies) vs KeepGrid Docs Pack ($19) vs Launch OS ($49) vs Pro add-on ($19/mo)
  • FAQ rewritten: 'Why pay if AI can generate this?' is the new top question. Added 'Can I buy only the documents?' and 'What's the difference between Launch OS and Pro?'
  • JSON-LD schema updated with all 6 offers + correct prices for Google Merchant rich-results
  • Backend: /api/checkout extended to handle 4 plan slugs (docs, install, bundle, annual) with proper Stripe modes (one-time payment vs subscription with setup-fee + recurring). Each plan maps to its STRIPE_PRICE_* env var
  • /api/projects accepts new plan field; /get-started reads ?plan= and ?rpStyle= query params from pricing-card and vertical CTAs to pre-select the right plan + RP style on intake
  • Stripe price IDs needed in env to fully activate: STRIPE_PRICE_DOCS, STRIPE_PRICE_INSTALL, STRIPE_PRICE_BUNDLE_SETUP, STRIPE_PRICE_RETAINER, STRIPE_PRICE_ANNUAL. Missing envs return clear 503 errors
v0.28seogrowthcontent

Verticals expansion — all 8 RP-style landings + browse hub

  • Five new vertical landing pages added on top of v0.27's three (relaunch, whitelist-only, PD/EMS): /redm-rp-server-discord-setup, /streamer-rp-discord-ops, /fivem-gang-economy-discord-setup, /fivem-public-server-onboarding, /fivem-semi-serious-rp-setup
  • Total 8 verticals now live, one for each of the 8 RP styles in the intake (serious, semi-serious, police-heavy, gang-heavy, whitelist-only, streamer, public, relaunch). Each is ~1500 words with hero, 4 pain points, 6 deliverables, 5 FAQ questions + FAQPage JSON-LD schema, intake auto-fill via ?rpStyle=
  • New /verticals hub page lets users 'browse by use-case' — color-coded cards with eyebrow + headline + description for all 8 verticals + audit/start CTA. Acts as a topic-cluster anchor for SEO
  • Sitemap updated: 9 new high-priority URLs (priority 0.85-0.9) covering keyword space like 'FiveM relaunch discord setup', 'serious RP whitelist system', 'FiveM police EMS discord template', 'RedM RP server discord setup', 'FiveM gang economy discord setup', 'streamer RP discord ops'
  • Each vertical's 'Generate my pack' CTA points to /get-started?source=vertical-X&rpStyle=X — when implemented in get-started.tsx (already wired in v0.13), the form pre-selects the right RP style automatically
v0.27growthseotrust

Roadmap kickoff — shareable Audit Reports + 3 vertical landings + RU sweep

  • Roadmap P0.4 — Shareable Audit Report: new public route /report/[invite] (e.g. /report/keepgrid). SSR-fetches the Discord invite + re-runs the audit, shows score + breakdown + findings + fix CTA. OpenGraph card with score in title ("Server X: Ops Score 72/100") for shareable previews. noindex (we don't want individual reports indexed) but fully crawlable for the recipient. 5-min edge cache per inviteCode
  • /audit results page got a 'Share this report' button (clipboard copy) so reviewers can forward to co-owner / head admin without re-running the form
  • Roadmap P1.5 — three vertical landing pages launched: /fivem-relaunch-discord-setup (Trust Rebuild pack with Reopening Charter, accountability log, grievance channel), /serious-rp-whitelist-system (calibrated rubric, panel review, recusal rules, quota), /fivem-police-ems-discord-template (department SOPs, 10-codes, rank ladder, academy track). Each ~1500 words, FAQ with FAQPage JSON-LD schema, vertical-specific intake auto-fill via ?rpStyle=. Sitemap updated
  • Roadmap P0.1 — Final RU residue sweep: '~90с' → '60–120с' on the last HIW step badge, three remaining absolute idempotency claims softened ('Никогда не дублирует настройку' → 'Спроектирован пропускать каналы и роли с совпадающим именем; для первого запуска рекомендуем тестовый сервер')
  • Audit form CTA copy: '11 AI-generated' → '13 AI-generated' (last 11→13 residue caught), 'in under 2 minutes' → 'install runs in 60–120 seconds'
  • New shared <VerticalPage> component (src/app/verticals/_components/vertical-page.tsx) with hero / pains / deliverables / FAQ / CTA structure. The other 3 verticals from roadmap (RedM, Streamer, Public→Structured) can adopt the same template in next batches
v0.26seocontent

Tool-page SEO complete — all 6 free tools now content-rich + FAQPage schema

  • Following the v0.25 pilot on /tools/whitelist-rubric, the remaining 5 tool pages got full SEO treatment: server-rules, ticket-routing, staff-sop, launch-checklist, permission-matrix. Each now has ~1000–1500 words of indexable content covering: 'why this matters', 'what the generator produces', 5 best practices, 5 common mistakes, 5-question FAQ, related tools, full-pack CTA
  • New shared <ToolFAQ> component emits both the visible <details> UI and a Schema.org FAQPage JSON-LD block — Google can now show the FAQ answers as rich snippets in search results for queries like 'FiveM whitelist SLA', 'Discord ticket routing best practices', 'FiveM staff hierarchy', etc.
  • All 6 tool pages share the same content structure for cross-linking — every page links to 3–4 related tools via descriptive anchors (not just 'check out our tools'), creating a strong internal-link cluster
  • Total new SEO surface added: ~7500 words across 6 pages, 30 FAQ Q&As schema-marked, 24 internal cross-links
  • /tools/whitelist-rubric updated to use the same shared FAQPage component (was using inline <details>)
v0.25trustcontentseocompliance

Audit pass v2 — timing tail-ends + public subprocessor list + tool-page SEO pilot

  • P0 timing cleanup: removed all remaining '~90s' / 'in 60 seconds' tail-ends across 11 landings (HIW step badges), /tools index, /tools/whitelist-rubric, /audit page title, dashboard install button, root layout meta. Now uniformly 60–120 seconds for install + 'about a minute' for single-doc generators
  • llms.txt rewritten to match shipped reality: 13 documents (was 11), Pro tier reflects weekly auto-scans / drift / SLA / email reports / Task Board / faction onboarding (was 'monthly updates'), 'never duplicates' softened to 'designed to skip items that already exist by name'
  • RU landing: 'ежемесячные сканы Ops Health' → 'еженедельные сканы Ops Health' in pricing intro; '60 секунд. Один клик. Discord готов.' → 'Один клик. Discord настроен за 60–120 секунд.'; absolute idempotency claims softened
  • P2: Privacy page now lists subprocessors publicly in a structured table (Anthropic, Stripe, Vercel, Neon, Discord, Resend, Upstash, Google Analytics) with purpose, data shared, and hosting region. Was 'available on request' — now visible to crawlers + buyers without friction
  • P2: New Cookies & Analytics section explicitly addresses EU/EEA / UK users: single first-party session cookie, GA with anonymized IPs, Do Not Track honored, no advertising/fingerprinting, full cookie consent banner under review
  • P1 SEO pilot: /tools/whitelist-rubric expanded from a thin form-only page to ~1500 words of indexable content — 'What a good rubric does', 'Best practices', 'Common mistakes', 5-question FAQ, 'Related tools' internal links, full-pack CTA. New seoContent prop on ToolForm so other 5 tool pages can be enhanced with the same pattern next
  • /audit meta title 'Score Your FiveM/RP Server in 60 Seconds' → 'in About a Minute' (consistent honesty)
v0.24contentlocalizationsecurity

10-locale alignment with v0.23 + security headers (CSP)

  • All 10 localized landings (RU, DE, ES, FR, PT, TR, PL, RO, AR, NL) brought into line with the English landing's v0.23 hero rewrite — 'ops layer for FiveM / RedM RP servers' positioning + 'Launch cleaner, onboard faster, keep staff aligned. Detect Discord drift before players feel it.' headline replaces the old 'Skip 30 hours of Discord setup'
  • Locale CTA hierarchy collapsed from 3 hero buttons to 2 (Generate + Free Audit) + inline tertiary text-links (Tools / How It Works). Header 'See Samples' button dropped on the 5 locales that had it
  • Auto-install timing badge '~90 seconds' → '60–120 seconds' across all 10 locales — meta description, JSON-LD schema, micro span, and any remaining mentions
  • Free Audit CTA renamed 'Free Ops Audit' across locales (matches /audit branding)
  • New defence-in-depth security headers applied to every response via next.config.ts: X-Frame-Options SAMEORIGIN, X-Content-Type-Options nosniff, Referrer-Policy strict-origin-when-cross-origin, Permissions-Policy locking down camera/mic/geo/USB/etc, Cross-Origin-Opener-Policy + Cross-Origin-Resource-Policy
  • Content-Security-Policy: tight script-src (self + GA + Stripe), tight connect-src (GA + Stripe + Discord), frame-ancestors self (blocks clickjacking), upgrade-insecure-requests
v0.23contentuxlocalization

Sample tables localized in 9 langs + CTA hierarchy redesigned

  • All 4 sample-output tables (Whitelist Rubric, Staff SLAs, Ticket Routing Map, Launch Checklist) localized in PT, FR, DE, ES, TR, PL, RO, AR, NL — column headers, row labels, footnotes. Combined with v0.19 RU localization, all 10 non-English landings now show fully native sample outputs
  • English landing CTA hierarchy tightened (auditor flagged 'too many similar CTAs'): header now has only one primary CTA (Generate — Free), removed 'See Samples' button. Hero went from 3 buttons to 2 (Generate + Free Audit), with 'How It Works' and 'Tools' demoted to inline text links below
  • Hero positioning rewritten per audit recommendation: 'The ops layer for FiveM & RedM RP servers — Launch cleaner, onboard faster, keep staff aligned. Detect Discord drift before players feel it.' (was 'Skip 30 hours of Discord setup'). Reframes from 'AI docs + bot' as a mechanism to 'ops layer' as the value
  • Auto-install section H3 timing badge updated: '~90 seconds' → '60–120 seconds' (matches honest range from v0.22 timing standardization)
  • Idempotency claim softened on auto-install card: 'safe to re-run' → 'designed to skip items that already exist by name' (matches v0.22 risk-sensitive copy pass)
v0.22trustcompliancecontent

Trust copy cleanup — removed contradictions across landings + trust pages

  • Resolved Auto-vs-Pro background-tasks contradiction: Bot Permissions / Security / Privacy now distinguish on-demand Auto Install (no passive monitoring) from Pro's opt-in weekly read-only scans (channel/role/permission metadata only — never modify the server)
  • Replaced 'Latest Anthropic model' (rots fast as Anthropic ships new versions) with version-agnostic 'Claude family' phrasing across all 11 landings + Terms
  • Standardized timing copy across all 11 landings: 'under 3 minutes' replaced with honest '3–5 minutes typical' (math: 30s intake + 2min generation + 60–120s install ≈ 3–5 min total). 'Install in 60 seconds' updated to '60–120 seconds' on the dedicated install section
  • Fixed 11→13 doc count residues: '+7 more' → '+9 more' on all 11 landings, '3 of 11 documents' → '3 of 13' in Terms + llms-full.txt
  • Data-Deletion page: rollback section updated from 'Launching in Installer 2.0' to 'Available now since v0.9' with clarification that account-deletion ≠ bot-rollback ≠ removing the bot
  • Softened absolute claims in Security: 'SQL injection: Impossible' → 'Mitigated via Prisma parameterized queries'; 'Idempotent: never duplicates' → 'designed to skip existing items by name; test server recommended for first runs'
  • Terms updated: explicit operator-details email path, EU/EEA/GDPR section with subprocessor list, age requirement clarified ('13 or jurisdiction minimum, whichever is higher'), trademark attribution for FiveM and Discord
  • Bot Permissions: added Discord Compliance Notes section covering intent scopes, no-AI-training policy, Premium Apps stance for future in-app features, Privacy Policy / Terms URLs in Developer Portal
  • Russian landing: localized sample-table column headers (Criteria → Критерий, Channel · Max response → Канал · Макс. ответ, Phase 1: Foundation → Фаза 1: Фундамент). Pro FAQ description rewritten from 'monthly updates and new templates' (outdated) to actually-shipped Pro features
  • 9 other locale landings: synced Pro tier description to actually-shipped recurring features (weekly Ops Health auto-scans, drift detection, email reports, Staff Task Board, faction auto-onboarding)
v0.21uiconsistency

Unified <SiteHeader> across all Next.js pages

  • 9 different bespoke headers consolidated into one shared <SiteHeader> component with three variants: public (logo + nav + Generate CTA), back (← Back link + context slot + custom right slot), minimal (logo + custom right slot only)
  • Public variant nav: Free Audit, Free Tools, Changelog. Renders consistent on /audit, /tools, /tools/*, trust pages, /login
  • Back variant: dashboard project pages (/dashboard, /dashboard/[id], /dashboard/[id]/install/[installId], /tools/[slug] back-to-tools)
  • Minimal variant: /get-started (price badge), /install-log (status badge)
  • All headers now sticky + backdrop-blur + uniform border-b — no more visual jumps between pages
  • Trust pages had a custom logo SVG; replaced with the standard text-only KeepGrid logo for visual consistency
v0.20infraperformance

Infra polish — SSR LangBanner, edge cache, Redis rate-limit

  • LangBanner refactored to server component: reads ?lang=xx from page searchParams, SSR-renders the localized TL;DR + flag picker. Now crawlable + indexable + cacheable, no client-hydration flash. Trust pages (bot-permissions, security, status, changelog) all wired
  • Edge cache headers added via next.config.ts: landings (EN + 10 locales) and trust pages get Cache-Control: public, max-age=0, s-maxage=300, stale-while-revalidate=600 — Vercel edge will serve cached responses for 5 min, 10 min stale-while-revalidate. Static SEO assets (sitemap, robots, llms.txt) get s-maxage=86400 (24h)
  • Status page kept on 60s cache (matters most when fresh)
  • Rate-limiter rewritten to support Upstash Redis via REST: when UPSTASH_REDIS_REST_URL + UPSTASH_REDIS_REST_TOKEN env vars are set, fixed-window counters live in Redis (shared across serverless instances, survives cold starts). Falls back to in-memory map when Redis envs are absent — local dev and current single-instance prod still work
  • Fail-open behavior: if Redis errors at request time, request is allowed through with a console.error logged — better than hard-blocking real users on a transient hiccup
  • All 6 rate-limited routes (audit, preview, projects, ops-scan, tools/generate, discord-scan) migrated from sync rateLimit() → async rateLimitAsync()
  • @upstash/redis added as dependency (~12KB gzipped)
v0.19contentlocalization

Localized landings full refresh + Trust pages multilingual banner

  • All 10 localized landings (PT, FR, DE, ES, RU, TR, PL, RO, AR, NL) — Pro tier card rewritten with the actual recurring features (weekly auto-scans, drift detection, email Ops Reports, Staff Task Board, faction auto-onboarding, doc regeneration). No more 'monthly updates' placeholder
  • Hero subtitle on every localized landing now lists the 8 RP styles + mentions Incident Reports and Ban Appeals docs
  • Trust pages (bot-permissions, security, status, changelog) gained a multilingual banner with 11 flag-emoji language picker + a 'page is in English, email for translation' contact path
  • /bot-permissions specifically renders a localized TL;DR (~3 sentences) when ?lang=xx is set — covers the Discord-Policy-required compliance summary in PT/FR/DE/ES/RU/TR/PL/RO/AR/NL
  • Translation quality second-pass on /get-started intake i18n: refined phrasing in FR (Places de joueur, Taille de l'équipe), PT (Prévia vs Pré-visualização), DE/RU/PL/TR/RO/NL (more natural describe prompts)
  • All 11 mentions of '11 documents' in i18n strings updated to '13 documents' to match shipped reality
  • Privacy / Terms / Data-Deletion deliberately left in English with email-for-translation banner — legal accuracy over machine translation
v0.18contentmarketing

Site copy refresh — 13 docs, RP styles, Free Tools nav

  • All 11 landings updated: '11 documents' → '13 documents' wherever it appeared (titles, meta descriptions, OpenGraph, hero copy, pricing card bullets, FAQ JSON-LD)
  • English landing hero now lists the 8 RP styles (Serious / Semi / PD-heavy / Gang / WL-only / Streamer / Public / Relaunch) and includes Incident Reports + Ban Appeals in the doc list
  • Pro tier description rewritten across landings: 'recurring updates' → weekly auto-scans, drift detection, email Ops Reports, Staff Task Board, faction auto-onboarding
  • Free Tools nav link added to all 11 landings (next to Free Audit) — directs to /tools index of 6 single-doc generators
  • FAQ entry on Ops Health updated to remove 'coming soon' for weekly scans + email reports (both shipped in v0.11)
  • Meta descriptions sitewide now mention Free Audit, Free Tools, and tuned-by-RP-style positioning
v0.17productops

Staff Task Board — web kanban for per-project work

  • Staff Task Board on the dashboard for paid projects: 3-column kanban (Todo / In Progress / Done) with per-project tasks
  • Tasks carry title, description, priority (low/normal/high/urgent), assignee (free-text — Discord username, role, real name), optional due date, status
  • Inline move (← → arrows between columns), inline delete, modal-based create and edit
  • Filters: by priority (Urgent / High / Normal / Low) and by assignee (top 5 assignees shown automatically)
  • Overdue indicator on cards whose due date passed while still not Done
  • New DB model Task with projectId FK and (projectId, status, updatedAt) index; migration provided
  • New API routes: GET/POST /api/tasks/[projectId], PATCH/DELETE /api/tasks/item/[taskId]
  • Auto-stamp completedAt when moving to Done; clear when moving back
v0.16productgrowthpositioning

Full 6-tool suite + 8th RP style (Relaunch)

  • Three new free tool generators launched: Staff SOP Generator (/tools/staff-sop), Launch Checklist Generator (/tools/launch-checklist), Discord Permission Matrix Generator (/tools/permission-matrix). Each is rate-limited 5/15min/IP, no signup, SEO-optimized with dedicated metadata
  • Six total standalone tools now live at /tools (full set from Phase 4 Growth checklist complete)
  • New RP style: Relaunch/Trust Rebuild — 8th and final vertical package from Phase 4. Applies a trust-reset posture to all generated docs: public changelog references, 'previous chapter' framing (no blame/drama retelling), small-cohort reopening pattern (50→100→full), staff accountability log, grievance channel, explicit Reopening Charter
  • All rpStyle enums synchronized across 4 API routes (/api/projects, /api/preview, /api/tools/generate, /api/projects/[id]/regenerate) and 3 UI components (get-started, doc-update-reminder, tool-form)
  • Sitemap + llms.txt updated with all 6 tool URLs and the 8-package catalog
  • ROADMAP growth checklist fully closed: all 6 lead-magnet generators shipped
v0.15productgrowth

Per-category install picker + free single-doc tools

  • Per-category install approval in the advanced install-options picker: opt out of Information / Community / Tickets / Voice / Staff categories before bot authorization. Skip list encoded in mode cookie, carried through OAuth callback, enforced by executeInstall with per-category skip pushStep entries
  • Three free single-doc generator pages launched at /tools — Whitelist Rubric, RP Server Rules, Ticket Routing — each produces one customized document tuned to server name, platform, RP style, staff size, factions. Rate-limited 5/15min, no signup, no account
  • New /tools index page with full pack upsell. Each tool page is SEO-optimized with dedicated title, description, canonical
  • Sitemap + llms.txt updated with all 4 new URLs
  • Tool generator events wired to GA: preview_started, preview_completed, audit_fix_clicked (for full-pack conversion)
v0.14productops

Incident + Ban Appeal docs, faction auto-onboarding

  • Two new docs generated automatically: Incident Report Templates (6 severity templates, triage SLAs, evidence handling) and Ban Appeal Workflow (cooldown table, review panel, scoring rubric, 4 verdict DM templates). Total now 13 docs
  • Faction auto-onboarding: owners add a faction in the dashboard → KeepGrid bot creates the matching Discord role (purple, hoisted, mentionable) immediately if the bot is installed
  • New faction roles are tracked in the install's created-items manifest so rollback still cleans them up
  • Faction name validation: letters/numbers/spaces/_-. only, 1-64 chars, duplicate guard
  • New endpoints: POST /api/factions/add
v0.13productpositioning

Vertical packages, launch calendar, doc drift refresh, shareable logs

  • RP style picker added to intake: Serious / Semi-serious / PD-EMS heavy / Gang-economy / Whitelist-only / Streamer / Public. AI prompt now modulates rules strictness, app length, enforcement language to match the chosen style — no more generic RP output
  • Launch Calendar on dashboard (launching-stage only): interactive 4-phase checklist (Foundation, Pre-Launch, Launch Day, Post-Launch) with 24 items across infrastructure, docs, Discord, testing, announcements. Target date + progress bar persisted in localStorage
  • Doc update reminder card: owners can update staff size, RP style, and factions in place and regenerate all 11 docs against the new state — no need to create a new project when the server evolves
  • New endpoint /api/projects/[id]/regenerate (works on ready/paid projects) — replaces docs atomically, restores original status on failure
  • Public read-only install log at /install-log/[installId] for support-ticket sharing. Exposes status, progress, summary, mode; redacts guild ID, snapshot, OAuth tokens, created-item tracker
  • Share-log button on install progress page copies the public URL in one click
v0.12productgrowthinfra

Funnel analytics, 11-lang intake, install modes, Tickets SLA

  • Google Analytics funnel events wired end-to-end: preview_started, preview_completed, generate_clicked, project_created, checkout_started, payment_succeeded, bot_authorized, install_started, install_completed, install_failed, rollback_started, ops_scan_run — conversion funnel finally measurable
  • /get-started is now fully localized into 11 languages (EN, PT, FR, DE, ES, RU, TR, PL, RO, AR, NL) with RTL support for Arabic; all 10 localized landings pre-pass ?lang= — no more English-only form for non-EN traffic
  • Install modes: choose Full / Roles-only / Channels-only / Docs-only before bot authorization. Picker in dashboard, carried through OAuth callback, enforced in executeInstall by per-phase gates
  • Tickets SLA tracking integrated into Ops Scan: counts open threads in Tickets category (or heuristic match), flags tickets stale > 24h and breached > 72h, surfaces in dashboard SLA panel and in weekly email report findings
  • Ops Scan snapshot now includes ticket metrics (openThreads, staleOver24h, breachOver72h, oldestHours) — tracked over time via existing scan history
v0.11productautomationgrowth

Weekly auto-scans + drift detection + email reports

  • Ops Health scans now run automatically every Monday 14:00 UTC for all paid projects with an installed bot — no manual trigger needed
  • Drift engine compares every scan against the previous one: new/removed channels, new/removed roles, permission flips (public→private or vice versa), new and resolved findings, score delta
  • Dashboard Ops Health card surfaces a Changes since last scan panel with granular drift items
  • Weekly Ops Report email delivered via Resend: score + grade, drift summary, top 3 findings with fixes, dashboard link
  • Cron endpoint secured via Vercel CRON_SECRET bearer auth; gentle 250ms pacing between guilds avoids Discord rate-limit spikes
  • Scheduled scans stored with scanType: 'scheduled' so owners can distinguish manual from automatic history entries
v0.10productmonetization

Ops Health — Pro tier scans + score history

  • Deep Ops Scan via installed bot: reads channel/role/permission data (not just public invite info) for more accurate scoring
  • Scoring across 5 categories: onboarding (35pts), structure (25pts), trust (15pts), growth (15pts), compliance (10pts)
  • Scan history per project — trend sparkline shows score movement over time
  • Dashboard card: current score + grade, latest findings with severity + concrete fix, last 5 findings expandable
  • Gated behind paid status: free tier shows Pro upsell card explaining the feature
  • Installer tracks complete state so scans only run on servers with active installs
  • New DB model OpsScan stores historical scans for diff + trend analysis
  • New API: POST /api/ops-scan, GET /api/ops-scan/history/[projectId], GET /api/ops-scan/[scanId]
  • Rate limit: 10 scans/hour/IP (manual trigger only for now; scheduled weekly scans in next release)
  • This closes Phase 3 (Ops Pivot) — Pro subscription now has recurring daily/weekly value beyond one-time install
v0.9producttrustsecurity

Installer 2.0 — dry-run preview + one-click rollback

  • Added dry-run install plan preview: scan your server, see exactly what will be created (every channel, role, pinned message) before executing anything
  • Added one-click install rollback: deletes every item KeepGrid created during that install; items that existed before are untouched
  • Pre-install snapshot: before the bot makes any changes, it records your server's current channel and role IDs for safe rollback reference
  • Plan export as JSON: download the install plan for offline review or audit
  • Failed-install rollback: even if an install fails partway, you can roll back the partial changes with one click
  • Dashboard UI overhaul: plan preview card, stat counters, filterable plan item list (all/creating/skipping), rollback confirmation dialog
  • New API routes: /api/install/plan, /api/install/rollback, /api/install/export-plan/[installId]
  • Updated bot-permissions page + landing FAQ to explain preview + rollback safety features
v0.8productgrowth

Free Discord Ops Audit — lead magnet

  • Launched /audit — standalone tool that scans any public Discord invite and returns a 0-100 Ops Score with concrete fixes across 4 categories (onboarding 40pts, structure 25pts, trust 15pts, growth 15pts)
  • No signup, no OAuth, no bot required — uses only Discord's public invite API
  • Audit findings pre-fill /get-started intake form when user clicks Fix button — lossless funnel
  • Added Free Audit button to hero + nav on all 11 landing pages, translated per locale
  • Rate limited to 10 audits per 15 min per IP
v0.7compliancetransparency

Trust Center + strategic pivot to Ops OS

  • Published Privacy Policy, Terms, Data Deletion, Security, Bot Permissions, Status, and Changelog pages
  • Documented every Discord permission the bot requests with clear removal instructions
  • Added GDPR/CCPA data request paths — email-based until self-serve UI ships
  • Published strategic roadmap pivoting KeepGrid from one-time install tool to daily Ops OS for RP servers
  • Prepared Free Discord Ops Audit as upcoming lead magnet
v0.6.1seo

SEO duplication hardening

  • All Vercel deploy URLs now 308-redirect to https://www.keepgrid.net/
  • Removed dangling aliases from archived keepgrid-site project
  • Updated canonical URLs in metadata across all routes
  • Added X-Robots-Tag: noindex on non-canonical hosts as defense-in-depth
  • Set NEXT_PUBLIC_APP_URL in production environment
v0.6analyticsseo

Google Analytics + sitemap canonicalization

  • Added Google Analytics (G-ME53LMPQWE) to all 11 static landings
  • Integrated next/script with afterInteractive strategy in Next.js root layout for SaaS pages
  • Updated sitemap.xml — all 12 URLs now use canonical www domain
  • Refreshed hreflang tags, robots.txt Sitemap directive, llms.txt references
  • Added /get-started to sitemap with priority 0.95
v0.5landingtrustcopy

Landing overhaul — 9 trust-building fixes

  • Hero rewritten: removed 'control layer' overpromise — now 'Skip 30 hours of Discord setup'
  • System Previews: replaced 4 placeholder boxes with real structured excerpts (scoring rubric, SLA table, routing matrix, launch checklist)
  • Removed false 'Real deliverables from real installs' claim
  • Removed outdated 7-day timeline that conflicted with 60-second positioning
  • New section: 'How it works' — 5 numbered steps with precise timings
  • New section: 'What gets delivered' — concrete numbers (11 docs / 30+ channels / 9 roles / ~90s)
  • New section: 'Compared to alternatives' — price anchoring vs DIY, Fiverr, resource packs, agencies
  • New section: 'Trust signals' — Claude Sonnet 4, Discord OAuth, idempotent installer, 63 tests, Stripe
  • FAQ doubled to 10 questions targeting cold-visitor anxieties
  • All 11 languages updated with consistent positioning and metadata
v0.4infraarchitecture

Monorepo merge + domain unification

  • Merged landing site and SaaS app into single Next.js monorepo
  • All 11 localized HTML files moved into /public with Next.js rewrites
  • Archived previously separate keepgrid-site repository
  • Single deploy, single domain, single git workflow
  • Ready for www.keepgrid.net DNS connection
v0.3.5securityaccessibilityperformance

Production-readiness audit + fixes

  • WCAG AA contrast fix: all muted text colors raised above 4.5:1 ratio
  • Keyboard-accessible language switcher (focus-within + button element)
  • Added visible focus states via :focus-visible everywhere
  • prefers-reduced-motion support
  • Arabic keywords properly localized
  • Fixed canonical URLs pointing to root instead of language path in pl/, ro/, pt/, fr/, de/
v0.3productmonetization

Paywall + plan selector + retry flow

  • Free tier now shows 3 of 11 documents; remaining 8 gated behind Unlock button
  • Download endpoint returns 402 Payment Required until project is marked paid
  • Added pricing cards on project page for install ($49) vs retainer ($19/mo)
  • Retry button for error state: re-runs generation with progress tracking
  • Generating status page with auto-refresh loader
  • Stripe checkout success banner with celebration
v0.2security

Security audit + rate limiting + prompt injection protection

  • In-memory rate limiter added to /api/preview (5/10min), /api/discord-scan (10/5min), /api/projects (3/hour)
  • Prompt injection protection: user input wrapped in <server_context> tags
  • Discord invite URL strictly validated — only discord.gg/discord.com allowed
  • Removed insecure auto-linking of Discord accounts by email
  • Added OAuth state CSRF parameter with secure cookie
  • Sessions upgraded to SameSite=Strict
v0.1productdiscord

Discord bot one-click installer

  • Built complete Discord bot installer: 5 categories, 27+ channels, 9 roles, full permission matrix
  • Adaptive role hierarchy based on staff count
  • Automatic faction role creation from intake
  • Pinned messages with customized content (welcome, rules, how-to-join)
  • Idempotent install — safe to re-run, skips existing items
  • Live progress tracking via polling (1.5s interval)
  • Install success/error states with retry button
v0.0launch

Launch

  • Next.js 16 app bootstrap with Prisma, Stripe, Claude API integrations
  • 11-language static landing site
  • AI document generation (11 docs) with Claude Sonnet 4 system prompt
  • Intake wizard with Discord invite auto-scan
  • Discord OAuth + email fallback login
  • 63 automated tests passing

Roadmap Highlights

Upcoming work tracked in ROADMAP.md:

  • Free Discord Ops Audit (next release) — standalone audit tool that scans an invite and returns an Ops Score with specific issues.
  • Installer 2.0 — dry-run preview, rollback, per-category approval.
  • Launch Pro 2.0 — weekly ops reports, SLA tracking, permission drift detection.
  • Vertical packages — Serious RP, Semi-Serious, Police/EMS, Gang/Economy, Streamer, etc.