Commit Graph

73 Commits

Author SHA1 Message Date
Ryan Hamamura
c6885a069b refactor: rename Go module from c4 to games
All checks were successful
CI / Deploy / test (pull_request) Successful in 14s
CI / Deploy / lint (pull_request) Successful in 25s
CI / Deploy / deploy (pull_request) Has been skipped
Rename module path github.com/ryanhamamura/c4 to
github.com/ryanhamamura/games across go.mod, all source files,
and golangci config.
2026-03-02 20:41:20 -10:00
Ryan Hamamura
38eb9ee398 refactor: rename game package to connect4, drop Game prefix from types
All checks were successful
CI / Deploy / test (pull_request) Successful in 16s
CI / Deploy / lint (pull_request) Successful in 25s
CI / Deploy / deploy (pull_request) Has been skipped
Rename game/ -> connect4/ to avoid c4/game stutter. Drop redundant
Game prefix from exported types (GameStore -> Store, GameInstance ->
Instance, GameStatus -> Status). Rename NATS subjects from game.{id}
to connect4.{id}. URL routes unchanged.
2026-03-02 20:31:00 -10:00
Ryan Hamamura
f71acfc73e fix: use format string for datastar.PostSSE in chat component
All checks were successful
CI / Deploy / test (pull_request) Successful in 16s
CI / Deploy / lint (pull_request) Successful in 24s
CI / Deploy / deploy (pull_request) Has been skipped
PostSSE requires a constant format string; pass "%s" with the URL
as an argument instead of passing the URL directly.
2026-03-02 19:47:05 -10:00
Ryan Hamamura
10de5d21ad refactor: extract standalone chat package from game-specific handlers
Some checks failed
CI / Deploy / test (pull_request) Failing after 11s
CI / Deploy / lint (pull_request) Successful in 25s
CI / Deploy / deploy (pull_request) Has been skipped
Create chat/ package with Message type, Room (NATS pub/sub + buffer),
DB persistence helpers, and a unified templ component parameterized by
Config (CSS prefix, post URL, color function, key propagation).

Both c4game and snakegame now use chat.Room for message management and
chatcomponents.Chat for rendering, eliminating the duplicated
ChatMessage types, chat templ components, chatAutoScroll scripts,
color functions, and inline buffer management.
2026-03-02 19:20:21 -10:00
Ryan Hamamura
7eadfbbb0c refactor: extract session helpers for player identity resolution
Add GetPlayerID, GetUserID, GetNickname to the sessions package.
Remove the inline player-ID-from-session pattern duplicated across
every handler in c4game and snakegame, and the local getPlayerID
helper in snakegame.
2026-03-02 19:16:09 -10:00
Ryan Hamamura
063b03ce25 refactor: extract shared player.ID type and GenerateID to player package
Both game and snake packages had identical PlayerID types and the snake
package imported game.GenerateID. Now both use player.ID and
player.GenerateID from the shared player package.
2026-03-02 19:09:01 -10:00
f47eb4cdf3 Merge pull request 'refactor: deduplicate persistence, add upsert queries, throttle snake saves' (#4) from refactor/game-efficiency into main
Some checks failed
CI / Deploy / test (push) Successful in 13s
CI / Deploy / lint (push) Successful in 25s
CI / Deploy / deploy (push) Failing after 17s
2026-03-03 05:02:04 +00:00
Ryan Hamamura
9a20467438 refactor: add save()/savePlayer() methods on game instances
All checks were successful
CI / Deploy / test (pull_request) Successful in 14s
CI / Deploy / lint (pull_request) Successful in 25s
CI / Deploy / deploy (pull_request) Has been skipped
Wrap free persistence functions in instance methods for cleaner call
sites (gi.save() instead of saveGame(gi.queries, gi.game)). Methods
log errors via zerolog before returning them.
2026-03-02 18:51:18 -10:00
Ryan Hamamura
cb5458c9fc ci: generate templ files before test and lint steps
All checks were successful
CI / Deploy / test (pull_request) Successful in 16s
CI / Deploy / lint (pull_request) Successful in 25s
CI / Deploy / deploy (pull_request) Has been skipped
2026-03-02 18:39:33 -10:00
Ryan Hamamura
bc6488f063 refactor: deduplicate persistence, add upsert queries, throttle snake saves
Some checks failed
CI / Deploy / test (pull_request) Failing after 15s
CI / Deploy / lint (pull_request) Failing after 23s
CI / Deploy / deploy (pull_request) Has been skipped
- Replace Create+Get+Update with UpsertGame/UpsertSnakeGame queries
- Extract free functions (saveGame, loadGame, etc.) from duplicated
  receiver methods on Store and Instance types
- Remove duplicate generateID from snake package, reuse game.GenerateID
- Throttle snake game DB writes to every 2s instead of every tick
- Fix double-lock in c4game chat handler
- Update all code for sqlc pointer types (*string instead of sql.NullString)
2026-03-02 16:56:29 -10:00
9c3f659e96 Merge pull request 'fix: add Enter key handlers to all auth and nickname inputs' (#3) from fix/enter-key-handlers into main
Some checks failed
CI / Deploy / test (push) Failing after 12s
CI / Deploy / lint (push) Failing after 24s
CI / Deploy / deploy (push) Has been skipped
2026-03-03 01:34:21 +00:00
Ryan Hamamura
2bea5bb489 chore: gitignore generated _templ.go files, track .templ sources
Some checks failed
CI / Deploy / test (pull_request) Failing after 13s
CI / Deploy / lint (pull_request) Failing after 24s
CI / Deploy / deploy (pull_request) Has been skipped
Generated _templ.go files are deterministic output from .templ sources,
same as output.css from input.css. Remove them from version control to
reduce diff noise and merge conflicts. Add build:templ and live:templ
tasks to the Taskfile so generation happens as part of the build.
2026-03-02 15:27:38 -10:00
Ryan Hamamura
4f1ee11fa3 fix: add Enter key handlers to all auth and nickname inputs
All checks were successful
CI / Deploy / test (pull_request) Successful in 14s
CI / Deploy / lint (pull_request) Successful in 25s
CI / Deploy / deploy (pull_request) Has been skipped
Pressing Enter on the username field in login/register or the nickname
field in the join-game prompt now submits the form, matching user
expectations. Also add *.templ to the gitignore allowlist.
2026-03-02 15:06:01 -10:00
Ryan Hamamura
8c6e5d24ac fix: add goose migration for sessions table
All checks were successful
CI / Deploy / test (push) Successful in 13s
CI / Deploy / lint (push) Successful in 25s
CI / Deploy / deploy (push) Successful in 28s
The sqlite3store library expects the sessions table to exist but does
not create it. On fresh deployments, the session store would fail.
Uses IF NOT EXISTS to be safe on databases where the table was created
outside of goose.
2026-03-02 15:00:07 -10:00
021215ed94 Merge pull request 'refactor: replace via framework with chi + templ + datastar' (#2) from refactor/remove-via into main
All checks were successful
CI / Deploy / test (push) Successful in 14s
CI / Deploy / lint (push) Successful in 24s
CI / Deploy / deploy (push) Successful in 1m58s
2026-03-03 00:47:20 +00:00
Ryan Hamamura
303c45cab1 feat: add downloader binary for client-side dependencies
All checks were successful
CI / Deploy / test (pull_request) Successful in 14s
CI / Deploy / lint (pull_request) Successful in 25s
CI / Deploy / deploy (pull_request) Has been skipped
Replace the curl-based Taskfile download task with a Go binary that
concurrently fetches datastar.js, datastar.js.map, daisyui.mjs, and
daisyui-theme.mjs. Update vendored libs to latest versions.
2026-03-02 14:34:53 -10:00
Ryan Hamamura
587f392b8b fix: serve datastar locally and clean up session/route config
Replace CDN-hosted datastar beta.11 with local v1.0.0-RC.7 to fix
client-side expression incompatibilities with the Go SDK. Also fix
quoted CSS class keys in data-class expressions, harden session cookie
settings (named cookie, Secure flag), simplify SetupRoutes to not
return an error, and regenerate templ output.
2026-03-02 14:34:39 -10:00
Ryan Hamamura
5120eef776 refactor: streamline routes to RESTful naming conventions
All checks were successful
CI / Deploy / test (pull_request) Successful in 13s
CI / Deploy / lint (pull_request) Successful in 23s
CI / Deploy / deploy (pull_request) Has been skipped
Remove /api/ prefix and consolidate route groups:
- /api/lobby/* -> /games, /snake, /logout (top-level)
- /game/{game_id} + /api/game/{game_id}/* -> /games/{id}/*
- /snake/{game_id} + /api/snake/{game_id}/* -> /snake/{id}/*
- /api/auth/* -> /auth/*
- Standardize snake join page to use return_url= (was return=)
2026-03-02 13:19:03 -10:00
Ryan Hamamura
fcc6b70e84 fix: warn when .env file is missing instead of silently ignoring
All checks were successful
CI / Deploy / test (pull_request) Successful in 13s
CI / Deploy / lint (pull_request) Successful in 24s
CI / Deploy / deploy (pull_request) Has been skipped
2026-03-02 12:42:10 -10:00
Ryan Hamamura
67d4dba37f fix: suppress gosec G117 on auth form signal structs
All checks were successful
CI / Deploy / test (pull_request) Successful in 7s
CI / Deploy / lint (pull_request) Successful in 47s
CI / Deploy / deploy (pull_request) Has been skipped
2026-03-02 12:40:02 -10:00
Ryan Hamamura
afd8a3e9d0 fix: resolve all linting errors and add SSE compression
Some checks failed
CI / Deploy / test (pull_request) Successful in 8s
CI / Deploy / lint (pull_request) Failing after 44s
CI / Deploy / deploy (pull_request) Has been skipped
- Add brotli compression (level 5) to long-lived SSE event streams
  (HandleGameEvents, HandleSnakeEvents) to reduce wire payload
- Fix all errcheck violations with nolint annotations for best-effort calls
- Fix goimports: separate stdlib, third-party, and local import groups
- Fix staticcheck: add package comments, use tagged switch
- Zero lint issues remaining
2026-03-02 12:38:21 -10:00
Ryan Hamamura
2aa026b1d5 refactor: remove persister abstraction layer
Some checks failed
CI / Deploy / test (pull_request) Successful in 8s
CI / Deploy / lint (pull_request) Failing after 46s
CI / Deploy / deploy (pull_request) Has been skipped
Inline persistence logic directly into game stores and handlers:
- game/persist.go: DB mapping methods on GameStore and GameInstance
- snake/persist.go: DB mapping methods on SnakeStore and SnakeGameInstance
- Chat persistence inlined into c4game handlers
- Delete db/persister.go (GamePersister, SnakePersister, ChatPersister)
- Stores now take *repository.Queries directly instead of Persister interface
2026-03-02 12:30:33 -10:00
Ryan Hamamura
8c3b3fc6ea refactor: replace via framework with chi + templ + datastar
Some checks failed
CI / Deploy / test (pull_request) Successful in 28s
CI / Deploy / lint (pull_request) Failing after 42s
CI / Deploy / deploy (pull_request) Has been skipped
Migrate from the via meta-framework to direct dependencies:
- chi for routing, templ for HTML templates, datastar for SSE/reactivity
- Feature-sliced architecture (features/{auth,lobby,c4game,snakegame}/)
- Shared layouts and components (features/common/)
- Handler factory pattern (HandleX(deps) http.HandlerFunc)
- Embedded NATS server (nats/), SCS sessions (sessions/), chi router wiring (router/)
- Move ChatMessage domain type from ui package to game package
- Remove old ui/ package (gomponents-based via/h views)
- Remove via dependency from go.mod entirely
2026-03-02 12:16:25 -10:00
Ryan Hamamura
2df20c2840 refactor: adopt portigo infrastructure patterns
Add config package with build-tag-switched dev/prod environments,
structured logging via zerolog, Taskfile for dev workflow, golangci-lint
config, testutil package, and improved DB setup with proper SQLite
pragmas and cleanup. Rename sqlc output package from gen to repository.

Switch to allowlist .gitignore, Alpine+UPX+scratch Dockerfile, and
CI pipeline with test/lint gates before deploy.
2026-03-02 11:48:47 -10:00
Ryan Hamamura
6d4f3eb821 fix: add explicit --login and --repo flags to tea commands
All checks were successful
Deploy c4 / deploy (push) Successful in 49s
2026-02-20 17:05:46 -10:00
Ryan Hamamura
e68e4b48f5 fix: resolve nil pubsub preventing live game updates
All checks were successful
Deploy c4 / deploy (push) Successful in 45s
v.PubSub() was captured at startup before v.Start() initialized NATS,
so both stores held nil and notify() silently no-oped. Replace the
PubSub interface with a callback that evaluates v.PubSub() lazily at
call time.
v0.1.4
2026-02-20 12:37:28 -10:00
Ryan Hamamura
91b5f2b80c deps: update ryanhamamura/via to v0.23.0
All checks were successful
Deploy c4 / deploy (push) Successful in 57s
Remove ContextSuspendAfter and ContextTTL options, which were
deleted upstream. Contexts now persist until SSE close beacon
or server shutdown.
v0.1.3
2026-02-20 12:06:51 -10:00
Ryan Hamamura
73b6e3bcc5 deps: update ryanhamamura/via to v0.21.2
All checks were successful
Deploy c4 / deploy (push) Successful in 1m0s
v0.1.2
2026-02-20 09:26:24 -10:00
Ryan Hamamura
ffd44ae56b deps: update ryanhamamura/via to v0.19.0
All checks were successful
Deploy c4 / deploy (push) Successful in 54s
v0.1.1
2026-02-19 12:13:00 -10:00
Ryan Hamamura
5a5cd08abb fix: use correct runner label in deploy workflow
All checks were successful
Deploy c4 / deploy (push) Successful in 59s
The workflow was hanging because `ubuntu-latest` doesn't match the
Gitea Actions runner registered with the `games` label.
v0.1.0
2026-02-19 11:20:42 -10:00
Ryan Hamamura
884650c68d feat: integrate via v0.18.1 context suspension and key throttling
Some checks failed
Deploy c4 / deploy (push) Has been cancelled
Upgrade via to v0.18.1 and configure context suspension timeouts
(5min suspend, 30min TTL) for clean reconnection behavior. Throttle
snake direction key inputs to 100ms to prevent wasted SSE round-trips
when keys are held down.
2026-02-19 11:14:35 -10:00
Ryan Hamamura
c5b863efdd chore: trigger CI/CD
Some checks failed
Deploy c4 / deploy (push) Has been cancelled
2026-02-19 09:38:00 -10:00
Ryan Hamamura
968c2cdb61 feat: add glowing effect to active player's pieces
All checks were successful
Deploy c4 / deploy (push) Successful in 42s
Pulsing box-shadow on the current turn's placed pieces makes the
turn state visible directly on the board rather than only in the
status banner.
2026-02-13 12:34:19 -10:00
Ryan Hamamura
c541ba56d4 fix: responsive C4 board on mobile and preserve chat input during morph
All checks were successful
Deploy c4 / deploy (push) Successful in 42s
Shrink board cells to 36px with tighter gaps on <768px screens so the
board fits on 375px phones. Add DataIgnoreMorph to the C4 chat input
so typing isn't disrupted when new messages arrive.
2026-02-13 12:26:24 -10:00
3593197271 feat: persist chat messages to SQLite (#1)
All checks were successful
Deploy c4 / deploy (push) Successful in 44s
2026-02-13 22:00:01 +00:00
Ryan Hamamura
08c20a1732 chore: re-upgrade via to v0.15.1
All checks were successful
Deploy c4 / deploy (push) Successful in 43s
The login bug was caused by missing RenewToken(), not the via update.
2026-02-13 11:43:31 -10:00
Ryan Hamamura
deff9b3859 fix: renew session token after login/register to persist session data
All checks were successful
Deploy c4 / deploy (push) Successful in 42s
Without RenewToken(), session data set during the action handler
wasn't surviving the redirect — the old pre-auth token was stale.
2026-02-13 11:35:37 -10:00
Ryan Hamamura
645d958041 revert: downgrade via to v0.15.0 to debug login regression
All checks were successful
Deploy c4 / deploy (push) Successful in 4s
Login on deployed server stopped persisting session data after the
v0.15.1 update. Reverting to isolate whether the via update caused it.
2026-02-13 11:29:17 -10:00
Ryan Hamamura
f238e126d3 chore: update via to v0.15.1
All checks were successful
Deploy c4 / deploy (push) Successful in 54s
2026-02-13 10:59:00 -10:00
Ryan Hamamura
9069530e47 feat: add in-game chat to Connect 4
All checks were successful
Deploy c4 / deploy (push) Successful in 43s
Add real-time chat alongside the game board, mirroring the snake chat
implementation. Fix mobile layout for both C4 and snake chats — expand
chat to full width and reduce history height on small screens.
2026-02-13 10:54:19 -10:00
Ryan Hamamura
e45559ecb3 chore: update APP_URL to games.adriatica.io
All checks were successful
Deploy c4 / deploy (push) Successful in 39s
2026-02-13 09:24:49 -10:00
Ryan Hamamura
e85271ab29 feat: stealth mode — replace game-related text with discrete symbols
All checks were successful
Deploy c4 / deploy (push) Successful in 40s
Replace "Game Lobby", "Connect 4", and "Snake" headings with colored
circles (●●●●) and tildes (~~~~) so the UI is less obviously a game
at a glance. Also neutralize the lobby description text and shorten
the back link.
2026-02-13 09:22:07 -10:00
Ryan Hamamura
9799387a32 fix: ensure data directory has correct ownership before starting container
All checks were successful
Deploy c4 / deploy (push) Successful in 41s
On a fresh VM, Docker creates the bind-mounted data/ directory as
root:root, but the container runs as games (UID 5). This causes
SQLite to fail with SQLITE_CANTOPEN. Create the directory with
correct ownership in the deploy pipeline.
2026-02-13 09:03:33 -10:00
Ryan Hamamura
dfc2111be5 feat: add CI/CD workflow and switch to bind mount for data
All checks were successful
Deploy c4 / deploy (push) Successful in 1m19s
Use a Gitea Actions workflow to deploy on push to main via
act_runner on the games VM. Switch from a Docker named volume
to a ./data bind mount for easier backup and persistence across
deploys.
2026-02-13 08:42:51 -10:00
Ryan Hamamura
427521505b feat: add Docker Compose deployment and serve assets via StaticFS
Embed full assets directory and serve with via's StaticFS instead of a
custom HTTP handler. Move SQLite DB to data/c4.db for clean volume
mounting. Add multi-stage Dockerfile, docker-compose.yml, and
.dockerignore.
2026-02-13 08:02:15 -10:00
Ryan Hamamura
b0449fbeb9 chore: rebuild CSS output 2026-02-12 15:10:38 -10:00
Ryan Hamamura
d2ed3cffd9 deps: update via to v0.15.0, remove vianats dependency
NATS is now built into via.New() automatically. Stores use the new
v.PubSub() accessor instead of the removed vianats package.
2026-02-12 15:10:18 -10:00
Ryan Hamamura
3d019fd948 feat: add snake multiplayer chat as sidebar with vivid player colors
Move chat to the right of the board using a flex wrapper that stacks
vertically on narrow screens. Restore original snake player colors by
removing the desaturation filter added with the dark theme.
2026-02-05 10:15:26 -10:00
Ryan Hamamura
0279615b36 feat: add back to lobby navigation on game pages 2026-02-05 09:55:43 -10:00
Ryan Hamamura
73128dc119 style: dark stealth theme with teal/burgundy pieces and cache-busting
Darken the DaisyUI theme and game board colors for a muted, low-chroma
aesthetic. Pieces use dark teal vs burgundy for subtle contrast.
Add MD5-based cache busting to the DaisyUI stylesheet link so CSS
changes are picked up without a hard refresh.
2026-02-05 09:51:36 -10:00