React 19 + TypeScript + Vite 7 app using Tailwind CSS 3 and shadcn/ui. Provides utilities for Genshin Impact players: Artifact Filter, Tier List Maker, Account Analytics, Team Builder, and Archive.
- UI: shadcn/ui, Radix primitives, Vaul (drawers)
- State: Zustand 5 (Immer + persist middleware)
- Desktop: Tauri 2 (
src-tauri/) - Edge: Cloudflare Workers (
functions/api/, Wrangler) - Quality: Biome (lint/format), Husky + lint-staged
- Testing: Vitest 4 + React Testing Library, Playwright (
e2e/) - Data Pipeline: Python scripts (
scripts/) withuv
Hosted on Cloudflare Pages (npm run build → dist/).
Navigation config: src/config/appNavigation.tsx. Layout shells: src/components/layout/.
Landing page with feature cards linking to each tool. Serves as the navigation hub.
Import game account data (via Enka UID fetch, GOOD JSON upload, or Mona/yas artifact-only scan), then analyze it across four tabs. Supports multi-account/profile management.
- Characters — Browse imported characters with their equipped artifacts and scores. Filter/sort by element, weapon type, or name. Tap a character to see artifact details and per-slot scores.
- Recommendations — View actionable upgrade suggestions generated by the Insight Engine. Each recommendation shows the strategy (equip, swap, upgrade, reroll, farm, fix main stat), affected slot, and projected score gain.
- Inventory — Browse all imported artifacts. Filter by set, slot, main stat, or substats. Mark artifacts as locked/trash. View which character an artifact is equipped on.
- Evaluation — Account-wide analytics: per-character build efficiency tiers (S/A/B/C/F), archetype classification (DPS/Support), stat coverage overview, and completion tracking. Deep-link to Artifact Filter for a specific character.
Define desired artifact builds per character, then compute which artifacts to keep or trash.
- Configure — Select a character, add/edit builds (artifact sets, main stats, substats, priorities). Import community preset builds or create custom ones. Reorder builds per character.
- Filters — View the computed filter result: for each artifact slot + main stat combination, see whether to keep or trash. Export the filter as a shareable PNG image or JSON.
Drag-and-drop ranking tool for characters and weapons.
- Characters — Drag characters into tier rows (SS/S/A/B/C/D). Filter by element or weapon type. Reset to default or clear all.
- Weapons — Same drag-and-drop tier ranking for weapons. Filter by weapon type.
Read-only game data encyclopedia for quick reference.
- Characters — Browse all characters with base stats, ascension materials, talent info. Filter by element, weapon type, rarity.
- Weapons — Browse all weapons with stats and passive descriptions. Filter by weapon type, rarity.
- Artifacts — Browse all artifact sets with 2-piece and 4-piece set effect descriptions.
Build and manage team lineups of 4 characters. Assign weapons and artifacts per character. Filter teams by element or region. Reorder, duplicate, or delete teams. Import/export team presets. The detail view (TeamOptDetail) shows damage calculation results with buff breakdowns, stat resolution, and team-wide optimization.
src/components/{domain}— Domain UI:account-data,artifact-builds,tier-list,team-comp,archivesrc/components/shared— Cross-domain:ItemPicker,ItemIcon,CharacterFilterSidebar, controls, tooltipssrc/components/ui— shadcn/ui primitives + custom widgets (tour,responsive-dialog,weighted-select)src/stores— One Zustand store per domain (persist tolocalStorage)src/data— Static JSON resources,types.ts,constants.ts, localization (i18n-ui.ts,i18n-app.ts,i18n-game.ts)src/lib— Pure logic: merge algorithms, filter computation, artifact scoring, build evaluation, insight engine, preset system, build utilities, damage calculation (team-comp/)src/hooks—useResolvedBuilds,useAsyncCompute,useMediaQuery,useGlobalScrollsrc/contexts—LanguageContext(EN/ZH),ThemeContext(per-element palette viathemeGenerator.ts)src/presets— Bundled preset JSONs for artifact builds, character tier lists, weapon tier listsscripts/— Python ETL (Enka, Hakush.in, HoYoLab, Fandom). Runupdate_data.cmdoruv run --project scripts/pyproject.toml scripts/<script>.pydocs/— Design docs, product specs, roadmap
- Static data (
src/data/*.json) is the immutable source of truth for game data. - User data enters via GOOD Format (JSON), Mona/yas Format (artifact-only JSON), Enka.Network (UID), or preset subscription → persists in
localStorage. Import merge rules: GOOD always wipes, Mona keeps character/weapon details but replaces all artifacts, UID upserts characters/weapons and deduplicates artifacts. - Preset system: presets in
src/presets/artifact-builds/serve as the Immutable Base. They DO NOT exist inuseBuildsStoredirectly. - Build Store (
useBuildsStore): Contains ONLY User Overrides, Custom Builds, and Ordering (characterToBuildIds). It is a Delta Store. DO NOT readbuildsdirectly from the store for scoring! - Build Resolution:
useResolvedBuilds(single char) /useAllResolvedBuilds(all chars) are the Single Source of Truth. They merge thePreset Base+Store Deltasto produce the effectiveBuild[].- Rule: Always use these hooks to get builds. Never traverse
useBuildsStore.buildsorpresetRegistrymanually.
- Rule: Always use these hooks to get builds. Never traverse
- Merge → Filter pipeline:
greedyMerge/smartMerge→computeFilters→ lock/trash scripts. Seesrc/lib/for all algorithms. - Zero
any: all external data (Import/API) must be typed and validated.
The src/lib/account-data/ module powers the evaluation and recommendation tabs:
- Build Evaluation (
buildEvaluation.ts): Per-character build assessment — archetype classification (DPS/Support), scaling stat detection, slot completion tracking, and efficiency tier ratings (S/A/B/C/F). - Insight Engine (
insightEngine.ts): Generates actionable recommendations using strategies: EQUIP (empty slot), SWAP (better artifact found), UPGRADE (level existing), REROLL (elixir/reroll), FARM (weakest slot), FIX_MAIN (wrong main stat). Each insight includes score differential and efficiency projections.
The src/lib/team-comp/ module implements a full damage calculation pipeline:
- Character implementations (
impl/): Per-character formula definitions, buff providers, and talent scalings. - Damage models (
damageModels.ts): Zone-based damage calculation (Base DMG, DMG Bonus, CRIT, RES, DEF, Elevate/Reaction). - Buff system (
damageBuffs.ts): Stackable team-wide and character-specific buffs with source tracking. - Optimizer (
optimizer.ts): Artifact assignment optimizer that maximizes total team damage. - Stat resolution: Idle → Combat stat pipeline with weapon, artifact, ascension, and buff contributions.
The functions/ directory contains Cloudflare Pages Functions that run on the edge. Currently used as a CORS proxy for the Enka.Network API:
- Route:
functions/api/enka/[[path]].ts— catch-all handler that proxies/api/enka/*→https://enka.network/api/* - Purpose: Bypass CORS restrictions when fetching player data from Enka.Network
- Frontend caller:
src/lib/account-data/enkaFetcher.ts— callsfetch("/api/enka/uid/<uid>")when running on Cloudflare Pages (ggartifact.com, *.pages.dev) or localhost:8788 (Wrangler). Falls back tocorsproxy.ioon other hosts (e.g. GitHub Pages). - Dev:
npm run devstarts Vite + Wrangler together so Functions are available locally on port 8788.npm run dev:viteskips Wrangler (Functions unavailable, fallback proxy used).
npm run dev— Vite + Wrangler dev server (Cloudflare Functions proxy)npm run dev:vite— Vite only (no Cloudflare Functions)npm run build/build:tauri— Production build (Web / Tauri Desktop)npm run lint/lint:fix— Biome check / auto-fixnpm run type-check— TypeScript check (src + tests tsconfigs)npm run test/test:watch/test:coverage— Vitest unit testsnpm run test:e2e/test:e2e:ui— Playwright e2e tests
You must use these to avoid explicit pipe (|) or redirect (2>&1) in the terminal:
npm run type-check:head/lint:head/test:head— Limits output to first 20 lines (avoids spam). Pass-- Nto change (e.g.npm run test:head -- 100).npm run type-check:tail/lint:tail/test:tail— Shows only the last 20 lines (error summaries). Pass-- Nto change.npm run type-check:headtail/lint:headtail/test:headtail— First 15 + last 15 lines (skips middle). Pass-- Nto change.npm run type-check:filter -- "Error"/lint:filter -- "Pattern"/test:filter -- "Pattern"— Greps output for pattern.- Example:
npm run type-check:filter -- "character5.ts"to find errors in a specific file.
- Example:
SidebarLayout: Drawer on mobile, fixed sidebar on desktop (lg+). Standard for pages with filter panels.AppBar: Sticky header. Actions viaActionConfig[]; dialog controls use ref forwarding (useImperativeHandle).- Mobile first:
Drawer(vaul) for mobile interactions,Popoverfor desktop. SeeItemPicker.tsx.
- Always use
cn()to merge styles. Layers:tailwind.config.ts→index.css→ inline. ThemeContext+themeGenerator.tsfor 9 color palettes.
i18n-ui.ts: Static UI strings. CRITICAL:t.ui()calls MUST use string literals (e.g.t.ui('common.save')), never dynamically constructed keys. I18n test will ensure all i18n-ui labels are referenced by code.i18n-app.ts: Dynamic terms, meant to be consumed via custom hooks ont, usually for labels of enum concepts. No tests.i18n-game.ts: Game entity names, auto-generated by scrapers.
- Unit tests in
tests/mirrorsrc/. Use@/path alias. - Store tests: use
useStore.getState()to verify state after actions.
- Avoid
|pipe and2>&1/>redirection (triggers safety review). - Never inline Python/JS code in terminal commands (e.g. python -c "..." or node -e "..."). Write a temporary .py/.js fil under temp/, run it, then delete it. Consider all side effects and failure modes, avoid dangerous actions and defer to user decision.
- Never run destructive scripts (regex replace, refactor, migration) directly on source files. Always write output to a
.newor.tmpcopy first, diff/inspect the result, and only then replace the original. - Before any bulk file transformation, make a backup copy of the target file.
- Test regex patterns with dry-run (print matches only) before applying replacements.