Workflows move to the repo root: deploy and CI build from web/, and a single
update-champions workflow replaces the old two-repo pipeline (scrape in data/,
copy into web/static/, redeploy). Go module becomes
github.com/tiennm99/loldle/data. Root README maps the three parts.
Drops .github/dependabot.yml, which existed solely to opt into routine
version updates. Dependabot alerts and security updates are repo-level
settings and both stay enabled, so vulnerabilities are still reported and
still get automated fix PRs.
What stops: weekly npm bumps and monthly GitHub Actions bumps. Non-vulnerable
dependencies now drift until a security advisory forces the issue.
Original config recoverable from 30670c8.
sync-data.yml now writes static/champions.json. This is the edit that had to
land with the deletion of public/: the workflow reports success regardless of
which path it writes, so a miss would have left the weekly sync green while
the live game 404'd on data load.
deploy.yml publishes build/ and passes BASE_PATH. Adds ci.yml, which runs
test, lint, and build on pull_request and pushes to main -- the repo had no
PR-triggered workflow before, so 'green before merge' was previously
unenforceable.
Deletes app/, components/, lib/, public/, next.config.mjs and
postcss.config.mjs, drops the Next and React dependencies, and swaps ESLint
onto eslint-plugin-svelte. sharp and unrs-resolver left pnpm's allowBuilds
because both arrived with Next and pnpm why now reports no dependents.
Port all six React components. State becomes $state, memos become $derived,
and the gameRef mirror that existed only to dodge a stale closure is gone --
runes read current values at call time, so one $state holds the game.
Initialization moves to onMount rather than $effect: the page is prerendered,
so loadChampions and localStorage must be browser-only, and onMount encodes
that structurally instead of relying on the effect body happening to read no
reactive state.
champion-search becomes a real combobox/listbox: input carries the combobox
role with aria-expanded and aria-activedescendant, options are list items
wrapping buttons, and Escape closes the dropdown. Visual output is unchanged.
next/image becomes plain img -- every usage already passed unoptimized.
classic-mode.js moves byte-for-byte. champion-data.js swaps the Next.js
env-var fetch prefix for asset() from $app/paths, which resolves to
/champions.json in dev and /loldle/champions.json in the deployed build.
getChampionImageUrl keeps returning an absolute Data Dragon URL, unwrapped.
Drops three exports with no callers: getAllChampions, getChampionByName,
getGuessedNames.
The characterization suite passes unchanged against the new location -- only
import specifiers moved, no assertions touched.
Add svelte.config.js (adapter-static, BASE_PATH-driven base), vite.config.js
(Tailwind v4 Vite plugin ahead of sveltekit), the src/ shell, and static/
holding a copy of champions.json plus .nojekyll.
Declares "type": "module" so Vite can load the .js config files; Next.js was
only unaffected because all its configs use .mjs. jsconfig keeps the @/* alias
so pnpm next:build stays runnable for side-by-side comparison during the port.
Next.js scripts move to next:* and both toolchains build from this commit.
Cover classic-mode comparison rules, game-engine state machine and
localStorage persistence, and champion-data search/seeding/loading with
Vitest. Storage keys are asserted literally so returning players' saved
games and stats cannot silently break.
Node environment with a hand-rolled localStorage stub; fixtures are four
hand-written champions so the weekly data sync cannot destabilise the
suite.
Replaces the upstream push-based fan-out with a scheduled pull, so this repo owns its own data refresh. Deploy is dispatched explicitly because a GITHUB_TOKEN push does not trigger workflows.
- bump actions/checkout to v7 and actions/setup-node to v7
- bump next to 16.2.10, react and react-dom to 19.2.7
- bump eslint-config-next to 16.2.10, tailwindcss and
@tailwindcss/postcss to 4.3.3, eslint to 9.39.5
- override @babel/core, js-yaml, and postcss to patched versions
- move pnpm build allowlist to pnpm-workspace.yaml
toISOString() returned UTC date, causing the daily game to reset at
UTC midnight rather than local midnight. Users in UTC+ timezones
would see yesterday's completed game until the UTC date rolled over.
- Replace vanilla HTML/CSS/JS with Next.js App Router + React components
- Game logic (champion-data, game-engine, classic-mode) moved to lib/
- UI split into modular components (game-board, champion-search, guess-grid, etc.)
- Add Tailwind CSS v4 with CSS variables for theming
- Immutable state updates, fetch deduplication, next/image for CDN images
- champions.json moved from assets/ to public/
The loldle repo is archived and read-only, so every push after a data
update failed with a 403. Consumers read champions.json from this repo
directly instead.
Checkout no longer overrides the token: the PAT existed only so the data
commit would trigger the sync workflow, and contents: write on the
default GITHUB_TOKEN covers the push.
- Add saveMarkdown in markdown.go rendering the Loldle classic-mode column
table (Champion | Gender | Genre | Range | Resource | Region | Lane | Year).
- main.go writes CHAMPIONS.md after champions.json on every scrape.
- update-champions.yml stages CHAMPIONS.md alongside champions.json so CI
commits both in lockstep.
- alt text on tile images now uses champion display name (e.g. Bel'Veth)
instead of the ID slug.
- update-champions.yml: cron/manual only, scrapes + commits
champions.json. Uses LOLDLE_PAT so the push retriggers sync.
- sync-champions.yml: runs on push to champions.json (or manual
dispatch), fans out to downstream repos via the sync_repo helper.
Single responsibility per workflow; chained via the push trigger.
Add push trigger (paths: champions.json) so direct edits to
champions.json auto-sync to miti99bot and loldle without needing a
workflow_dispatch. Scraper + commit steps skip on push events (the
data is already committed); sync step runs when either changed=true
from the scraper path OR the trigger is push. Default GITHUB_TOKEN
commits don't retrigger workflows, so no self-loop.
- Single LOLDLE_PAT secret for all downstream repos (miti99bot + loldle).
- sync_repo() takes (repo, dest-path, optional post-copy command);
add a target by appending one line.
- DRYs up duplicate clone/copy/commit/push blocks.
Mirrors the miti99bot push step — clones tiennm99/loldle, copies
champions.json into public/, commits and pushes. Gated on
LOLDLE_PUSH_TOKEN secret; step is a no-op when unset.
Replaces the repository_dispatch notification flow. After a successful
champions.json commit in loldle-data, this workflow now clones
miti99bot, copies the file, regenerates champions-data.js via the
project's build script, and commits+pushes to miti99bot main.
Token secret renamed MITI99BOT_DISPATCH_TOKEN -> MITI99BOT_PUSH_TOKEN
to reflect the new scope (contents:write on tiennm99/miti99bot).
After a successful commit of champions.json, send a repository_dispatch
(type: loldle-data-updated) to tiennm99/miti99bot so its sync workflow
pulls the latest data into its loldle module. No-op when
MITI99BOT_DISPATCH_TOKEN is unset.
Direct wiki page requests return 403 due to Cloudflare JS challenge.
Switch to MediaWiki parse API which returns rendered HTML without
blocking. Also match img[alt='Official'] in lane detection.
4-stage pipeline: fetch ddragon champions, enrich with release dates
(wiki scrape), regions (Universe API), and lanes (wiki scrape).
Concurrent gender detection via goroutines with semaphore.