Botswain · Systems architecture

Website Capability Registry

Reverse-engineered from the real commit histories of anekdotnik, sudoky and pozdravok — what we keep rebuilding, and what to share.

3
projects analyzed (commit-by-commit)
228
commits studied (189 + 21 + 18)
~24
recurring capabilities mapped
4
★★★ reinvented in all three
The insight: the same ~15 capabilities recur across all three projects, each solved 2–3 different ways (Metrica vs Umami, Vercel vs Cloudflare, DB-primary vs static-first). That overlap is the raw material — and the duplication is the cost the registry exists to stop.
The three projects

Same problems, different stacks

 anekdotniksudokypozdravok
WhatJokes site (~43k)Sudoku gameGreetings catalog (~12k)
StackNext 16 + PostgresVanilla JSNext 15 + Drizzle
HostVercelCloudflare Pages+Worker+D1Vercel / Node
AnalyticsYandex Metrica + 1st-partyUmamiMetrica (off)
DataDB-primaryD1 edgestatic-first, DB-optional
Live?Yes (monetization-blocked)YesNot launched
Phase 1 = inventory only. This maps what exists and what's worth sharing. It does NOT build the bootstrap system or versioning machinery yet — per the brief, a capability graduates from "registered" to "extracted as a skill" only when a second project actually needs it. Inventory first; abstraction on demand.
Deliverable A

Project evolution audit

Each project independently re-derived SEO, analytics, share, favorites and a design system — and each hit variants of the same bugs. None of those lessons reached the next project except by memory.

anekdotnik 189 commits

Arc: create-next-app → "jokes only" → Postgres-as-truth in 2 days → engagement before SEO → 6-week dormancy → analytics + LLM tagging → 20k external import → honest P&L → ranker.

  • Discovered: sitemap-index, two-part thin-page rule, silent-degrade analytics, enum-pinned resumable tagging, "pageviews are the revenue unit"
  • Mistake: the 60-topic taxonomy (biggest SEO effort) returns ~0 traffic

sudoky 21 commits

Arc: full offline game in 2 same-day commits → 4-month gap → i18n → almost the entire product (Worker+D1, Umami, streaks, duel) in one Aug-13 burst.

  • Discovered: Worker+D1 daily-challenge backend, CORS/offline-graceful API, Umami wrapper discipline
  • Mistake: live wrong-canonical domain + fabricated rating (see Live Findings)

pozdravok 18 commits

Arc: design-first with ad slots day one → static-first/DB-optional architecture → scraped 12k greetings → popularity-weighted SEO → still unlaunched (example.ru).

  • Discovered: static-first/DB-optional layer, AI-discoverability (llms.txt, GEO), CLS-safe ad slot, canvas share-image
  • Mistake: committed 12k scraped texts against its own rule; data-in-code OOM
Deliverables B & C

Coverage across the lifecycle

Every recurring capability, by project. The ★★★ rows are reinvented in all three and are the first consolidation targets; ★ rows are genuinely project-specific and should stay that way.

CapabilityaneksudokypozdrPriority
SEO foundation★★★
Analytics + event taxonomy★★★
Share button★★★
Favorites (localStorage)★★★
Programmatic long-tail pages★★
AI-discoverability (llms.txt, GEO)★★
Share-as-image (canvas/OG)★★
Data-access repository layer★★
Admin CRUD + auth★★
LLM content pipeline★★
Deployment★★
DB-on-serverless hardening★★
Monetization (RSYA/ads)★★
Voting / rating
Progression / streaks
i18n
mature partial / scaffolded absent
The registry

High-value capability records

Each with its universal-core vs configurable split. Install/validate procedures come in Phase 2, only for capabilities we actually extract.

SEO Foundation Kit ★★★

Core: canonical/OG/robots/JSON-LD emitters, sitemap-index pattern, param stripping, the two-part thin-page rule (noindex AND sitemap-exclude). Config: site URL, title templates, thresholds, JSON-LD types. All three reimplement it — top extraction target.

Analytics + Taxonomy ★★★

Core: a silent-degrade queue-and-flush wrapper, allowlisted event enum, sendBeacon, IP rate-limit before DB work, length-normalized dwell. Config: provider (Umami vs Metrica — market-driven) + event vocabulary.

Engagement Kit ★★★

Core: share targets + Web Share API (with the iOS synchronous-blob fix), localStorage store with SSR guards + cross-tab sync. In all three, near-zero project-specific.

LLM Content Pipeline ★★

Core: structured-output enum pinning, resumable idempotent runs, sync-vs-batch, prompt caching, the replace-vs-merge hazard, dry-run-before-spend. Config: taxonomy, prompt, model.

Share-as-Image ★★

Core: fitFont auto-size, taint-free canvas, R2/S3 SigV4 upload, branding composited (models garble text), per-item error isolation. Config: templates, model.

DB-on-Serverless Hardening ★★

Core: bounded pool (the recurring outage), Lightsail SSL, admin-vs-app roles, public-endpoint pre-parse throttle. Nearly all universal for Vercel + managed Postgres.

Same problem, different solution

Consolidation targets

Where the projects diverge — decide what to unify and what to keep configurable.

ProblemanekdotniksudokypozdravokVerdict
AnalyticsMetrica + 1st-partyUmamiMetrica (off)Provider configurable; share wrapper+taxonomy
Host/computeVercel + PGCF Pages+Worker+D1Vercel + DrizzleTwo families; don't force one
Content storageDB-primaryD1static, DB-optionalStatic-first is more portable — but runtime file, not source module
Identitycookie voter_keyanon device-idlocalStorageOne small "no-accounts" identity util
Structured dataper-page JSON-LDfabricated rating ⚠️full generators + llms.txtConsolidate on pozdravok's; never fabricate ratings
Reinvention within a project is just as costly: anekdotnik runs two taggers and linked comics twice; sudoky triplicated its Sudoku engine ("keep in sync by hand"). Duplication drifts — the registry exists to stop it.
Deliverables D & E

Proposed skills & bootstrap

Thin skills over one per-project site.config, not a framework. Every skill must pass the test: will it save time, reduce mistakes, or improve quality on the next project?

seo-core P0

Emit head + sitemap-index + robots + JSON-LD from config; validate (canonical == domain, sitemap resolves, no fabricated data). All 3 reimplement it; 2 have live bugs it prevents.

analytics-core P1

Provider-configurable wrapper (Umami | Metrica) + standard event taxonomy + "SPA next must fire a pageview." Reconciles 3 divergent implementations.

engagement-kit P1

Share + favorites, with the iOS synchronous-blob fix baked in. Built 3× with the same recurring bugs.

db-serverless P1

Pool bounds + roles + pre-DB rate-limit + migration checklist. The most-repeated outage; Vercel+PG family only.

llm-content-pipeline P2

Enum-pinned resumable classify/generate. Only one mature instance — extract when a 2nd need appears.

NOT skills

Scrapers (legal risk), Sudoku engine, duel server, swipe deck, voting/streaks internals. Genuinely project-specific.

Bootstrap flow (E)

new-project <name> --stack next|static --host vercel|cloudflare --market ru|intl
  → 1 site.config  → 2 select capabilities  → 3 configure from config
  → 4 validate each  → 5 deploy-readiness report

Every step is what the 3 projects already did — manually, inconsistently, with the bugs the registry catalogs. The bootstrap makes the proven path the default. The CLI + versioning + practice-discovery are deferred until a 2nd site consumes the same skills.
Guardrails to encode

Hard-won lessons every future project inherits

The highest-value output: rules paid for in real outages and dead features.

  1. Measure before scaling. anekdotnik's biggest SEO effort (60-topic taxonomy) returns ~0 traffic while 3 curated pages carry 28%. Don't build a matrix on assumed demand.
  2. Pageviews are the revenue unit — a reading loop that produces no navigation is invisible. Sank both infinite scroll and untracked swipe. Any SPA "next" must fire a virtual pageview.
  3. Scaffolded ≠ done. All three shipped inert monetization/analytics for months (Metrica ID empty, ads off, example.ru). Count it done only when it's live and firing.
  4. Data-in-code doesn't scale. pozdravok's 224k-line content module OOMs the build and rendered 52 MB pages. Large content → runtime file / DB; paginate before loading 10k items.
  5. Content sourcing is a legal + monetization risk. pozdravok committed ~12k scraped third-party texts against its own rules (RSYA ban risk). Any shared scraper = owned/licensed sources only, never auto-commit.
  6. CSV metrics lie. A Metrika CSV was ~3× understated vs the live UI → a bogus growth claim. Compare like-for-like from the live report.
  7. Footguns: ON DELETE CASCADE, regex-only screening, and colliding migration numbers across branches all bit anekdotnik. Bake into the DB skill's checklist.
  8. Build for demand, not ahead of it. sudoky's fully-built duel server sits dark; monetization mocks never shipped. Capital tied up before validation.
Byproducts → route to Howard

Real issues found on live / near-live sites

Incidental but valuable: the history pass surfaced concrete, fixable problems.

Live sudoky.net — SEO regression

canonical, OG, sitemap.xml, robots.txt, and JSON-LD all point at a stale fikratius.github.io/Sudoku/ instead of sudoky.net (left at Aug-13 go-live). Plus a fabricated aggregateRating 4.8/1250 and manifest/OG referencing PNGs that aren't in the repo. → a contained fix brief.

Pre-launch pozdravok — legal / RSYA risk

~11,854 scraped third-party greetings are committed & served against the repo's own stated rule, labeled CC-BY though not owned. An RSYA "non-unique content" ban risk and copyright exposure — best resolved before launch. → operator decision.

Pre-launch pozdravok — hygiene

Still on placeholder example.ru; build needs a 6 GB heap workaround (the data-in-code OOM). Launch-blocking.

How I'll handle these

They're Howard's repos. I'll package the sudoky SEO fix as a ready brief on your go, and bring the pozdravok scraping question to you as a decision (it's a content/legal call, not a code bug).

Deliverable G

Prioritized implementation plan

P0 = build now (repeated, high-value, low ambiguity) · P1 = build next (needs standardization) · P2 = investigate (insufficient evidence). Not everything becomes a skill.

P0 build now

  • guardrails.md checklist — the 8 lessons; near-zero cost, highest ROI
  • seo-core skill — all 3 reimplement it; 2 have live bugs
  • Fix sudoky.net SEO regression — live, contained

P1 build next

  • analytics-core — reconcile Umami vs Metrica
  • engagement-kit — share + favorites + iOS fix
  • db-serverless module + checklist
  • Decision: pozdravok scraped content

P2 investigate

  • llm-content-pipeline (1 mature instance)
  • deploy-core (two families)
  • monetization-slot (nothing earns yet)
  • bootstrap CLI · versioning · practice-discovery

Where it should live

  • New repo website-capabilities for the registry + docs.
  • Claude Code skills for executables as they graduate.
  • Botswain stays orchestration; no product code.

Sequencing rationale

Prove the extract-and-validate loop on seo-core first: if it saves time on the next SEO setup and its validator catches the wrong-canonical class of bug, that earns the P1 extractions. P2 waits for a real second consumer — the discipline that keeps this a compounding library, not a framework nobody asked for.