Commit Graph
13 Commits
Author SHA1 Message Date
ogrechkoandClaude Sonnet 5 48d618e6ec Add favicon matching the in-app logo icon
src/app/icon.svg — Next.js's file-convention route, auto-served and linked
in <head> (takes precedence over the existing default favicon.ico for
modern browsers). Same accent-colored rounded square + white Gamepad2
glyph as the header logo.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GteWhnWKTmnXcsd5jx6H7u
2026-08-21 05:48:46 +00:00
ogrechko 65044fa828 Taller canvas + real background design for all 4 game templates
Phone screenshots showed the canvas was short and squat (960x600, 8:5)
leaving most of the screen blank, with Clicker's hero list and Quiz's
answer options too cramped to tap comfortably. Also the dark-mode canvas
background was the same near-black as the page, so games had no visible
frame and read as flat/undesigned.

Bumps canvas to 960x720 (4:3) and uses the extra room to enlarge hero
rows, quiz options/lifelines, and maze/snake grid cells. Adds a themed
gradient frame around the canvas in play-session.tsx and replaces each
scene's flat background fill with a subtle top-to-bottom gradient.
2026-08-01 12:01:59 +00:00
ogrechko 13bea64bb6 Mobile: bigger HUD text, wider canvas, on-screen D-pad for Maze/Snake
Games were unreadably small on phones (fixed-px HUD text scaled down
by the Phaser FIT canvas) and Maze/Snake were unplayable on touch
(keyboard-only input). Bumps HUD font sizes ~1.4x across all 4 scenes,
tightens play-session's mobile padding so the canvas fills more of the
screen, and adds a tappable D-pad wired through a new registry
"touchDirection" event that feeds the same direction-buffering logic
the keyboard already uses.
2026-08-01 10:54:38 +00:00
ogrechkoandClaude Sonnet 5 a61ef772db Add a 4th template: classic Snake
New templateType "snake" alongside quiz/clicker/maze — additive, not a
redesign, so it's wired through every existing per-template
enumeration point (schema, types unions, scene factory, builder
dispatch on create/edit/AI-review pages, template icon maps) following
the pattern each already established.

games.templateType is a plain SQLite text column with a TypeScript-
only enum (no SQL DDL behind it) — confirmed via drizzle-kit generate
that adding "snake" produces zero migration, same as every in-place
template redesign this session.

Bounded arena (no maze-style wall authoring — keeps the builder trivial:
width/height/startLength/targetLength/wrapAround, nothing else).
Movement is a self-rescheduling delayedCall loop rather than a fixed
interval, since the step interval itself shrinks as the snake grows;
speed curve sanity-checked standalone before wiring it in. Discrete
per-cell snapping (not tweened, unlike the maze's glide) — that's the
authentic blocky Snake feel, not a shortcut. Standard collision rule:
the tail cell is excluded from the self-collision check unless this
step eats food, since the tail is vacating that cell.

Progress resumes the exact live state (body/direction/food/score) —
Snake has no natural level-boundary checkpoint the way the other three
templates do, so unlike their coarse-grained resume this restores
precisely.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-08-01 03:49:26 +00:00
ogrechkoandClaude Sonnet 5 c035650063 Maze: Pac-Man-style dots, ghosts, and continuous movement
Full redesign of the Maze template (same templateType: "maze" — plain
text column, no migration needed): dots (*) to eat, power pellets (O)
that frighten ghosts, ghost spawns (G, 0-4), and continuous glide
movement with buffered turns instead of one-cell-per-keypress. Win
condition confirmed with the user explicitly: collect every dot and
pellet, then reach the exit — kept the exit tile rather than switching
to classic Pac-Man's "no exit, board-clear wins," since this app's
maze identity is built around it.

Ghosts chase via BFS pathfinding (reusing the same BFS shape the
maze's own reachability check already used, just retargeted at the
live player position each tick) and flee via simple greedy
distance-maximizing when frightened. The reachability check itself
generalized from "is the exit reachable" to "is every dot, pellet, and
the exit reachable" — same guarantee, now covering the actual win
condition instead of just the exit. Verified precisely: a maze with a
reachable exit but one walled-off dot is correctly rejected.

Continuous movement is tick-based, not real physics: a repeating timer
steps the player in the buffered direction (or continues straight) if
open, tweening the sprite's pixel position between cells for a glide
feel rather than snapping. Same 3-lives-on-capture, coarse-grained
resume (position + collected keys + lives, ghosts reset to spawn on
reload) as the other templates' resume behavior.

The one existing maze game on production validated cleanly against
the new schema unchanged (lives defaults to 3, its dots were already
reachable) — no data migration needed this time.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-08-01 03:35:31 +00:00
ogrechkoandClaude Sonnet 5 be53908471 Clicker: more content, hero role labels, prestige shop
More levels (30->60) and heroes (6->10) in the flagship dungeon so the
curve stays climbable at the new range. Each hero row now shows
whether it improves click damage, hits passively, or both — derived
from its existing bonus fields (heroRoleLabel), never hand-authored,
so it can't drift out of sync with what the hero actually does.

New permanent account-wide upgrade shop, funded by a currency
("crystals") earned by clearing clicker dungeons — kept deliberately
separate from the real coin wallet (wallets/coinTransactions, spent on
real-money purchases and manual save), so clicker play can never be
used to farm real-money-equivalent value. Same atomic-transaction
shape as spendCoins in src/lib/wallet/service.ts throughout:

- claimCompletionReward is idempotent per (user, game) via a unique
  index — replaying and re-winning the same dungeon can't farm
  crystals twice. Verified through the real HTTP API, not just the
  service layer: claim, claim again (no-op), confirm balance
  unchanged.
- buyPrestigeUpgrade does the same read-check-debit-increment
  atomicity check as spendCoins — verified an insufficient-crystal
  purchase leaves no partial debit.
- The two upgrades (click damage %, gold gain %) apply automatically
  in every clicker game via a new accountBonuses prop threaded through
  GameCanvas/PlaySession (same optional-passthrough shape already used
  for initialState/onProgress) down into the registry the scene reads.
- /api/games/[id]/complete correctly rejects non-clicker games (400) —
  the reward is clicker-specific.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-08-01 03:04:55 +00:00
ogrechkoandClaude Sonnet 5 f5833a1988 Upgrade Clicker to a Clicker Heroes-style monster battler
Full redesign of the Clicker template (same templateType: "clicker" —
plain text column, no migration needed): a battlefield with an emoji
monster that has real HP, click/DPS damage, boss fights every 5th
level (HP x4, 20s timer — timing out just resets the boss rather than
punishing progress), and heroes that level up repeatedly with scaling
cost (Clicker Heroes' defining mechanic, replacing the old one-time
"buy an upgrade" model).

No image pipeline available, so the "2D graphics" ask is met with
large emoji as monster art backed by real animation instead: an
HP bar that shifts green -> yellow -> red, camera shake + a red flash
+ a squish tween on every hit, floating "-N" damage numbers, and a
small coin burst on every kill.

Verified the HP/boss/gold/hero-cost curve with a standalone script
before wiring it into the scene (same approach used for the quiz
checkpoint math): boss multiplier lands only on levels divisible by 5,
HP growth and hero cost compounding both check out. Builder form and
AI-generation prompt updated to match the new shape.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-08-01 02:36:44 +00:00
ogrechkoandClaude Sonnet 5 ff1b2ff6f9 Turn the quiz template into "Кто хочет стать миллионером?"
Full redesign of the Quiz template (same templateType: "quiz" key —
it's a plain text column, not a SQL enum, so no migration needed):
15-level money ladder with two guaranteed checkpoints (level 5, level
10), three classic lifelines (50:50, помощь зала, звонок другу — all
simulated client-side, weighted by difficulty band), a "Забрать"
walk-away option, and questions organized into 7 categories x 5
difficulty bands.

Ships with a 105-question bank of real, fact-checked trivia (history,
geography, science, literature, film/music, sport, general knowledge)
per the explicit "don't invent anything, use facts" requirement —
deliberately sticks to foundational/uncontestable facts rather than
"current record holder" style trivia that goes stale. A game session
draws one random unused question per level from that level's band
pool, so repeated playthroughs don't see the same 15 questions.

Checkpoint math verified against the classic rule (wrong answer keeps
the highest checkpoint reached, not partial credit) via a standalone
script before wiring it into the scene. Progress save/resume, the
builder form (added category+band fields), and the AI-generation
prompt (now requires real verifiable facts, structurally constrained
to the 7-category enum) all updated to match the new shape.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-07-31 22:27:49 +00:00
ogrechkoandClaude Sonnet 5 43347bc31b Send Cache-Control: no-store on every page to defeat upstream caching
Every page here is personalized (session, coin balance, owned games) —
no intermediate proxy should ever cache one. Traced a report of a
stale UI (missing header content that had already shipped) to caching
somewhere between the app and the client — nginx isn't even on this
VM, the user's reverse proxy (Nginx Proxy Manager) lives on a separate
one I can't inspect. Rather than debug an opaque hop I don't control,
close it from this side: explicit no-store on every HTML/API response
except /_next/static, which keeps its normal long-lived immutable
caching since those filenames are content-hashed by the build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-07-31 22:10:10 +00:00
ogrechkoandClaude Sonnet 5 e682c7df13 Fix mobile header layout, add resumable progress + coin wallet
Header nav was splitting into three lines on mobile (logo / nav /
logout floating right with a big gap) — applied the same order-last
wrap pattern already proven in top-tickets/project-claude, so nav
drops to its own scrollable row instead.

Bigger feature: player progress now survives closing the tab, for all
three templates, not just Clicker. Each Phaser scene reports its state
through the same registry-callback pattern already used for onFinish
(onProgress), and reads an initialState to resume instead of always
starting fresh. Autosave fires every 10 minutes for free; an instant
manual save costs coins.

New coin economy (src/lib/wallet/): a wallet + transaction ledger per
user, atomic grant/spend via db.transaction() so two concurrent spends
against a low balance can't both succeed (verified with a real race
test — exactly one wins, balance never goes negative). New accounts
get a 20-coin signup bonus so manual save is testable before any real
payment method exists.

Real-money purchases are scaffolded but deliberately not wired to a
provider yet — user hasn't picked one. /api/wallet/purchase creates a
pending order and returns a clean "not configured" error, same shape
as the AI/LDAP not-configured responses elsewhere in this project. The
payment abstraction (src/lib/payments/provider.ts) is the one seam a
real adapter needs to fill in later.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-07-31 21:56:49 +00:00
ogrechkoandClaude Sonnet 5 3d5497fae9 Add missing .dockerignore
Without it, COPY . . in the Dockerfile overwrote the container's npm-ci
node_modules with the host's — a native-binary mismatch that surfaced
as a missing libnode.so.115 during the build-time page-data pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-07-31 17:43:29 +00:00
ogrechkoandClaude Sonnet 5 c9a6c27a7a Build MVP: launcher, constructor, and AI game generation
A self-hosted, Roblox-flavored game platform: browse/play published
browser games, build them by hand or by describing them to an LLM.
Fully independent from top-tickets — separate repo, DB, port (8082).

- Auth: email+password accounts (argon2, httpOnly session cookies),
  no admin/agent split — every account can create and play.
- Three game templates (quiz, clicker, maze), each a zod schema paired
  with a Phaser 4 Scene that renders purely from a validated instance
  of that schema — manual and AI-generated games hit the same
  renderer, so a saved game is always guaranteed to load and run. The
  maze schema BFS-validates that the exit is reachable from the start.
- Manual constructor: per-template builder forms, draft/publish/edit/
  delete, a launcher grid of published games, a full-bleed play page.
- AI generation: Anthropic API key configured under Settings → AI
  (encrypted at rest, validated with a live call before saving, same
  shape as top-tickets' mailbox/LDAP settings). Generation uses the
  SDK's zodOutputFormat/messages.parse to force schema-shaped JSON
  output, with one retry feeding back the validation error. Output
  always prefills the manual builder for review — never auto-published
  blind. Clean, distinct error message when no key is configured yet
  (no silent fallback exists here, so it doesn't pretend one does).
- Docker Compose on port 8082 (bakes in the busy_timeout=30000 SQLite
  pragma from day one — top-tickets hit this build-time race twice).

Deferred: more templates/genres, drag-and-drop level editor, likes/
leaderboards, AI-generated sprite assets, multiplayer, moderation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QcXH24ky6zjk2UyK5oZUPH
2026-07-31 17:40:30 +00:00
ogrechko df16c90832 Initial commit from Create Next App 2026-07-31 17:06:29 +00:00