diff --git a/README.md b/README.md index e5d359501..b1162fff9 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@

CI Status Invite Lucky + Lucky on top.gg Node.js 22 TypeScript 5.9 Discord.js 14 @@ -34,13 +35,18 @@ Lucky is a **production-grade, self-hosted Discord music bot** — built as a Ty Unlike Groovy, Rythm, or Hydra (all shut down by third-party enforcement), Lucky can't be taken offline because **you host it.** Every feature is included — no paywall, no premium tier. -- **Live demo**: [lucky.lucassantana.tech](https://lucassantana.tech) +- **Live demo**: [lucky.lucassantana.tech](https://lucky.lucassantana.tech) - **Invite to your server**: [Add Lucky now](https://lucky.lucassantana.tech/invite?utm_source=github&utm_medium=readme&utm_campaign=readme-badge) --- ## ✨ Features +

+ What Lucky does — feature overview +
Everything most servers need, in one bot — see it live. +

+ ### 🎵 Music Player - **Multi-source playback**: YouTube, Spotify, SoundCloud - **Smart autoplay**: Recommendations based on your listening history diff --git a/assets/screenshots/landing-features.png b/assets/screenshots/landing-features.png new file mode 100644 index 000000000..144b65e45 Binary files /dev/null and b/assets/screenshots/landing-features.png differ diff --git a/decisions/2026-07-12-brand-asset-regen-tooling.md b/decisions/2026-07-12-brand-asset-regen-tooling.md new file mode 100644 index 000000000..d2d1214df --- /dev/null +++ b/decisions/2026-07-12-brand-asset-regen-tooling.md @@ -0,0 +1,171 @@ +# Brand-asset regeneration — hybrid resvg-frame + Gemini-mascot via inference.sh + +- **Date:** 2026-07-12 +- **Status:** Accepted — pilot completed (see Pilot outcome + FINAL DECISION below: keep the original mascot) +- **Deciders:** Lucas Santana +- **Method:** `/research-and-decide` — CLI-verified capability probe + web-doc research + artifact-only `decision-critic` (returned NEEDS_REVISION → decision revised to hybrid) + +## Context + +The README hero `assets/lucky-social-preview.png` (1280×640 baked raster) is off-brand: a +neon-glow cat mascot with **gold/orange** stripes + eyes, plus overlaid text chips +("Lucky", "TypeScript", "React", "849+ Tests", "4 Packages") where some accents render gold. +Brand palette is Discord **Blurple `#5865f2`** + **Neon Pink `#ec4899`** (gold explicitly +removed — `packages/frontend/branding/BRANDING_GUIDE.md`). No source pipeline composes this +PNG (repo grep: referenced only as a static file in `README.md` + `docs/TOP_GG_SUBMISSION.md`). + +Scope corrections established during research (do NOT route these through AI): + +- **Production `og-image.png`** (served to web) is a SEPARATE asset, already code-generated at + build time via **resvg** from SVG in `packages/frontend/scripts/prerender-seo.ts` — clean, + brand-colored, no gold. Out of scope. +- **`assets/lucky-logo.svg`** is off-brand **purple** (`#7c3aed`/`#8b5cf6`/`#a78bfa`/`#c4b5fd`) + → fix by deterministic fill-swap, not AI. Separate cleanup. +- **`assets/outline-layer-{all,mid,gold}.svg`** are orphan design exports, referenced nowhere + → ignore (YAGNI). +- **`--color-lucky-gold-*`** CSS vars (`index.css:130-132`) are legacy compat aliases already + holding pink values, 0 live refs, slated for the planned migration-cleanup PR → leave as-is. + +So the only asset that genuinely needs a raster generator is the hero mascot. + +## Decision + +**Hybrid, not pure-AI** (this is the critic's decision-flipping correction): + +1. **Deterministic frame, AI-free.** Rebuild the hero's frame — background grid, layout, and + text chips — by **reusing the proven resvg SVG→PNG pipeline** already in + `prerender-seo.ts`. Text rendered from SVG = crisp, exact brand colors, **zero regen + drift**. AI never touches rendered text (dissolves the maskless-regen text-mangling risk on + short strings like "4 Packages"). +2. **AI only for the neon-cat mascot raster** — the one element that cannot be clean SVG + (soft neon bloom + gradients). Model: **`google/gemini-2-5-flash-image`** primary + (mascot has no text → Pro's text-rendering edge is moot; Flash is cheaper), escalate to + **`google/gemini-3-pro-image-preview`** (NanoBanana Pro) only if Flash quality is + insufficient. Both accept `images: [""]` (CLI auto-uploads — verified) + + natural-language edit prompt. +3. **Two mascot variants** (keep-gold vs strip-to-blurple/pink) for operator/Maria to compare, + with cross-variant **consistency via reference-image** (feed variant-1 as `images[]` to + generate variant-2) — **NOT** a trained LoRA (LoRA training is overkill for two images). + +**Rejected candidates:** Grok (weak/unreliable text — but text is now SVG-side, so moot +anyway); FLUX-Dev-LoRA (LoRA training overkill + text quality undocumented); Seedream/Reve +(strong but Gemini dominates on instruction-edit + reference consistency). **Rejected +approaches:** pure-AI whole-hero regen (maskless → text drift); full SVG rebuild of the mascot +(neon-glow raster art does not translate to clean vector). + +## Consequences + +- **Positive:** text is deterministic + brand-exact; AI cost bounded to the mascot; no LoRA + training infra; reversible per-call (all models same CLI, pay-per-image, no lock-in). +- **Negative / risk:** reference-image mascot consistency is **UNVERIFIED** — it is the single + load-bearing claim (critic's strongest objection). Must be pilot-tested before scaling. +- **Neutral:** the neon cat becomes the documented primary mascot (currently undocumented). + +## Delivery channel (updated 2026-07-12) + +inference.sh CLI hit `insufficient balance` (zero credits). Rather than fund it, the operator +has a **Gemini Pro (Advanced) subscription** which includes **Gemini 3 Pro Image / "Nano +Banana Pro"** — the _same model_ as `google/gemini-3-pro-image-preview`. So the mascot +generation runs via the **Gemini web app driven by Claude-in-Chrome**, at no incremental cost. +The inference.sh CLI (`images: [""]` auto-upload, verified) remains the +**scriptable fallback** once credits are added — preferred if the work ever needs to be +batched/reproducible rather than one-off. + +## Pilot outcome (2026-07-12) — KEEP EXISTING MASCOT + +Pilot ran via Gemini web (Nano Banana Pro). **Technical result: PASS** — two consistent +variants generated (gold-accent A; blurple-accent B), in-thread edit held pose/composition +exactly (Gemini reported "Confirming Color Consistency"). So the critic's load-bearing +consistency risk is **resolved: reference/in-thread consistency works.** + +**Aesthetic result: REJECT (operator).** Both regens read "too AI-ish" vs the original hero +cat, which "feels more welcoming." Root cause: from-scratch regen launders out the original's +asymmetry/hand-drawn character (the source of its warmth) into a generic uniform neon-sign +look. This fires the **"pilot output worse than existing → keep existing"** trigger. + +**Decision: keep the original mascot as-is; do NOT replace it via AI regen.** The gold in the +mascot contributes warmth the operator values — treat it as intentional, not drift. Any future +palette tweak to the mascot must be an EDIT of the original raster (preserve its exact +character), never a from-scratch regen — and even that is not currently wanted. AI image-gen +via Gemini is a validated capability for OTHER assets (fresh graphics with no beloved +predecessor), just not for re-deriving this mascot. + +## Iteration 2 (2026-07-12) — img2img RECOVERS the warmth + +Operator chose to keep iterating (better prompt + explore other skills) rather than abandon. +Root cause of "too AI-ish" pinned by cropping the original: warmth = **simplicity + solid +dark fill + chunky roundness + minimal detail** (sticker/kawaii), which from-scratch text +regen launders into busy symmetric line-art. **Fix = img2img from the original crop** (not +text-to-image): feeding the real cat as a reference preserved its exact cozy character while +cleaning it up. Result accepted as the right direction. + +**Working method (Gemini web via Claude-in-Chrome, no paid CLI):** + +- Reference upload into the Gemini composer = **same-machine clipboard paste**: + `osascript … set the clipboard to (read POSIX file … as «class PNGf»)` then focus composer + - `cmd+v`. CRITICAL: the browser being driven and the machine running `osascript` must be + the SAME host — pasting the Mac clipboard into a REMOTE (Windows) Chrome types a literal "v" + (different clipboard). Use `list_connected_browsers` → `select_browser` to pin the local Mac + (`isLocal:true`) first. +- `file_upload` MCP tool is BROKEN (rejects host paths, wants a `files` content param not in + its schema) — do not use; clipboard paste is the workaround. +- Download-back is blocked: Brave prompts a native "Save As" dialog (unautomatable), JS + cross-origin fetch of the `googleusercontent` blob is CORS-blocked, curl 403s (needs + cookies). Operator downloads from their own browser, or fund inference.sh for scriptable + local-file img2img. +- Prompt levers that kill the "AI-ish" feel: "SOLID dark-filled", "chunky/round", "minimal + detail, no busy line-work", "sticker/emote", keep exact reference. + +Skills installed to inform brand prompt craft: `anthropics/skills@brand-guidelines`, +`inference-sh/skills@logo-design-guide`. + +## FINAL DECISION (2026-07-12) — KEEP THE ORIGINAL MASCOT + +After a `/debate` (5 lenses) and testing ALL three production paths, the operator chose to +**keep the original mascot untouched.** Evidence trail (each shown to the operator, each +rejected): + +1. **Text-to-image regen** (Nano Banana) → "too AI-ish" (busy line-art, generic). +2. **img2img from the original** → preserved warmth but "too rounded, weird" (over-rounded blob). +3. **Hand-authored vector SVG** (rendered via resvg — the production pipeline; neon-glow + filter DID survive resvg, so the vector path is technically viable) → "straight up ass": + thin strokes, weak glow, stiff geometric proportions vs the original's thick plump richly- + glowing warmth. Confirmed the debate's DESIGN-CRAFT prediction: vector-DIY hits a quality + ceiling for warm organic neon character. + +**Conclusion:** the original mascot is genuinely strong and none of AI-regen / img2img / +vector-DIY beat it. Stop mascot work. If a definitive polished mascot is ever wanted, the +reliable path is a **human illustrator** (debate plan B), not another generation attempt. +**Redirect visual-identity effort to higher-ROI, taste-safe gaps:** the off-brand PURPLE +`lucky-logo.svg` (deterministic recolor to Blurple/Pink) and missing product/dashboard +screenshots in the README. + +## Logo close-out (2026-07-12) — RASTER SUFFICIENT, vector DEFERRED + +Second `/debate` (5 lenses) on "how to get a crisp scalable cat logo": **unanimous — ship +the raster package, defer vector.** The raster (resampled from the 375px crop, gold kept) +covers every use case for an 11-guild Discord bot (web logo, favicon, avatar, embeds). No +print/large-format/merch need has been articulated, so crisp-vector ROI is contingent on a +requirement that does not exist yet. Tracing the neon glow yields muddy geometry +(pre-threshold mitigation = manual tuning = same fidelity ceiling the hand-vector hit). + +**Deferred vector fallbacks (only if a print/merch need materializes):** (a) bounded ~30-min +image-to-svg trace of the line geometry + re-glow via SVG feGaussianBlur (render via resvg), +show operator; (b) if that is muddy/stiff → commission a human illustrator. Vector/illustrator +skills on skills.sh for that day: `shhac/skills@image-to-svg` (trace), `rknall/…@svg-logo-designer`, +`sfkislev/flue@illustrator`. + +**Visual-identity thread CLOSED for now:** mascot = keep original; logo = the raster cat +package (delivered, operator wires when ready); vector = deferred. Higher-ROI identity gap +still open if wanted later: README product/dashboard screenshots. + +## Revisit when + +- **Pilot fails** (mascot inconsistent, wrong hue, or artifacts) → flip the mascot to manual + edit or keep the existing cat; do not iterate AI blindly. +- **Gemini iteration exceeds 3 rounds** → stop, keep existing mascot or escalate; the cost has + overrun the SVG-alternative amortization point. +- **A clean standalone mascot source** later exists (SVG/high-res raster) → reference-image + quality improves; re-pilot. +- Text ever needs to go INTO an AI-generated asset → re-evaluate model text-rendering (Gemini + ~94% short-text, Reve typography engine) rather than defaulting to SVG. diff --git a/decisions/2026-07-12-readme-presence-visual-proof.md b/decisions/2026-07-12-readme-presence-visual-proof.md new file mode 100644 index 000000000..531e08277 --- /dev/null +++ b/decisions/2026-07-12-readme-presence-visual-proof.md @@ -0,0 +1,82 @@ +# README presence — ship public-landing visual proof; plumbing is trivial, not a blocker + +- **Date:** 2026-07-12 +- **Status:** Accepted +- **Deciders:** Lucas Santana +- **Method:** `/research-and-decide` — research agent (live-site + competitor survey) + artifact-only `decision-critic` (NEEDS_REVISION → revised after human-browser verification) + +## Context + +Lucky's original goal was "more presence." The GitHub README is text/table-strong (positioning, +badges, feature/comparison/command tables, quickstart) but has **zero product visuals** — a wall +of text. The mascot + logo threads already closed (see +`decisions/2026-07-12-brand-asset-regen-tooling.md`); this decides where presence effort goes next. + +**Verified in a real browser (the critic demanded this; a fetcher had returned 403/404):** + +- `https://lucky.lucassantana.tech` is **UP** and **genuinely polished** — dark theme, neon-cat + logo, hero + CTAs, a "What Lucky does" 6-card feature grid, "A real web dashboard" section, + a dev/self-host architecture-card section, Apache-2.0 footer. Fully public (no auth). +- The top.gg listing **exists** at bot id `962198089161134131` (the `839686019796811776` ref that + 404'd is a **wrong/stale bot id**). +- Constraint: the _authed_ dashboard needs Discord OAuth login, which the assistant may NOT perform. + But the **public landing is assistant-screenshottable**, removing the operator bottleneck. + +## Decision + +**Ship visual proof from the polished PUBLIC LANDING, now, assistant-driven.** Concretely: + +1. Capture clean screenshots of the live landing (hero, "What Lucky does" grid, the + dashboard/feature section) and add them to the README with short captions. No auth, no operator + dependency, no design work. + **Delivered scope (this PR):** shipped `assets/screenshots/landing-features.png` (the + feature grid). The hero shot is deferred pending #1818 (landing still renders "Apache 2.0" + while the project is ISC) so the README doesn't advertise the wrong license. +2. Fix the two verified plumbing bugs (trivial, not a blocker): the README live-demo link + (`href="https://lucassantana.tech"` → `https://lucky.lucassantana.tech`) and the wrong top.gg + bot id (`839686019796811776` → `962198089161134131`); add a top.gg badge/link. +3. **Optional operator follow-up (not a blocker):** a real authed-dashboard screenshot or a short + Loom, if wanted — the landing already _claims_ "a real web dashboard"; a real shot would _prove_ + it. Gated on operator (login), so it is a nice-to-have, done last. + +Framed honestly: this is **cheap, obvious polish** (empty README + polished landing already built), +**not a validated growth lever.** No heavy measurement plan (YAGNI for a solo OSS bot). + +## Alternatives considered + +- **top.gg listing audit as the #1 lever** (research's top pick) — folded in as bug #2 (fix the id + + badge), but the listing already exists, so it is a small fix, not the headline. +- **Bot-in-action demo GIF / screencast** — higher effort (needs a Discord test server + capture + + edit); deferred. A landing screenshot is far cheaper for equal first-impression lift. +- **Authed dashboard screenshots as the primary asset** — rejected as the _primary_ because the auth + constraint makes the operator the bottleneck; demoted to optional follow-up. +- **"Differentiate because competing music bots omit visuals"** — DROPPED. The critic correctly + flagged it as inferred from n=3 behavior, not evidence that visuals convert or don't. +- **Architecture diagram / secondary bot-lists / mockup galleries** — low impact-per-effort, deferred. + +## Consequences + +- **Positive:** README gains real visual proof in one assistant-driven pass; two broken external + links fixed; the polished landing (already built, currently under-leveraged) starts working for + the project. Reversible (README edit). +- **Negative / risk:** landing-UI changes will stale the screenshots (low maintenance cost — re-snap). + Presence may not be Lucky's actual growth bottleneck (discovery/community could matter more) — so + this is bounded polish, not a growth bet. +- **Neutral:** authed-dashboard proof remains an open optional follow-up on the operator. + +## Revisit when + +- The landing page UI is redesigned → re-capture the README screenshots. +- Evidence emerges that presence is NOT the growth bottleneck (e.g. traffic data shows the Discord + community drives adoption, not the README) → stop investing in README polish. +- The operator wants to prove the _dashboard_ specifically → add the authed screenshot/Loom follow-up. + +## Related defects (found during this decision — file as issues) + +- README live-demo link href mismatch (bug #1 above). +- Wrong top.gg bot id `839…` vs live `962…` (bug #2 above). +- **License discrepancy:** README/LICENSE say **ISC**, the landing footer says **Apache 2.0** — + authoritative source must be reconciled (legal). +- Node version drift: README says Node 22, the toolchain decision (`decisions/2026-07-12-*toolchain*`) + moved to Node 24. +- Test-count claim conflict: README "~2500 tests" vs the social-preview hero "849+ Tests".