Community game database and crafting tools for Vagrant Story (PS1, 2000). Part of the criticalbit.gg gaming tools platform.
Browse weapons, armor, gems, grips, materials, consumables, and enemies. Build inventories, plan equipment loadouts, and run a crafting workbench that finds optimal multi-step combine paths against your current inventory and selected workshop. Import save data straight from a PS1 emulator memory card.
Pairs with vagrant-story-api.
- React 19 + TypeScript + Vite
- TanStack Router — type-safe file-based routing
- TanStack Query — server state and caching
- shadcn/ui + Tailwind CSS v4 (OKLCH theme, dark mode default)
- Zod v4 — schema validation
- ky — HTTP client with automatic token refresh
- orval — generates React Query hooks, TS types, Zod schemas, and MSW mocks from the API's OpenAPI spec
- MSW — API mocking for tests
- Vitest — unit/component tests
- Husky — pre-commit hooks (lint, test, build)
- Node.js 24+
- pnpm
pnpm install
pnpm dev # https://localhost:5173 (proxies /api to production API)Set VITE_API_URL=http://localhost:8000 in .env to point at a local backend instead of the production API.
Auth cookies are issued for .criticalbit.gg and marked Secure, so testing signed-in flows locally requires HTTPS on a .criticalbit.gg subdomain. One-time setup:
- Add
127.0.0.1 local.criticalbit.ggto/etc/hosts(or the Windows equivalent). - Install mkcert and trust the local CA:
mkcert -install. - Generate the dev cert into
.certs/(gitignored):mkdir -p .certs mkcert -key-file .certs/key.pem -cert-file .certs/cert.pem local.criticalbit.gg localhost 127.0.0.1 ::1
pnpm dev picks up the cert automatically when it exists and falls back to plain HTTP otherwise. Visit https://local.criticalbit.gg:5173 (not localhost) so the browser can see the .criticalbit.gg auth cookies after sign-in.
pnpm dev # Dev server
pnpm build # Type check + generate routes + bundle
pnpm lint # ESLint
pnpm test # Vitest watch mode
pnpm test:run # Vitest single run
pnpm format # Prettier
pnpm generate-api # Regenerate API client from backend OpenAPI specPre-commit runs lint-staged → eslint → vitest → full build. All must pass.
Routes live in src/routes/ (file-based, auto-generated routeTree.gen.ts). Route components are thin wrappers that import page components from src/pages/. Shared components are in src/components/, business logic in src/lib/, and the API client + types in src/lib/game-api.ts.
See CLAUDE.md for routing conventions, the pattern for adding a new item type, and styling rules.
Cookie-based auth designed to work with the companion API:
- AuthProvider (
src/lib/auth.tsx) — React context trackingisAuthenticated,isLoading,email,userId - Automatic token refresh (
src/api/api.ts) — 401 responses trigger a refresh attempt; concurrent requests are coalesced into a single refresh call - Session check on load —
GET /auth/mevalidates the session on mount - Auth in router context —
authis available in routebeforeLoadfor guards
Flow: backend sets httpOnly app_access + app_refresh cookies on login → all requests use credentials: "include" → on 401 the client POSTs /auth/refresh → original request retries transparently → on refresh failure onUnauthorized clears auth state.
orval generates type-safe React Query hooks, TypeScript types, Zod schemas, and MSW handlers from the backend's OpenAPI spec.
pnpm generate-apiGenerates into src/api/generated/:
hooks/—useQuery/useMutationwrappers with integrated Zod validationtypes/— TypeScript types for all request/response schemaszod/— standalone Zod schemas (form validation, manual use)mocks/— MSW mock handlers for tests
Configuration in orval.config.ts. Defaults to http://localhost:8000/openapi.json. CI sets OPENAPI_URL to verify generated types stay in sync.
ThemeProvider supports dark/light/system. useTheme() reads/sets, ThemeToggle cycles modes. Persists to localStorage (app_theme) and applies .dark / .light to <html> for Tailwind dark mode. Theme: ice blue primary, dark mode default. Headings use Geist Pixel Line; body uses Geist Variable.
- Global mutation errors —
MutationCacheinQueryClientcatches all mutation errors and toasts via sonner - Per-mutation opt-out — set
meta: { skipGlobalError: true }to handle locally getErrorMessage()(src/lib/api-errors.ts) — extracts human-readable messages from FastAPI error shapes (detailas string, array, or object)
pnpm test # Watch mode
pnpm test:run # Single run
pnpm test:coverage # With coverage
pnpm test:ui # Visual UIrenderWithFileRoutes() (src/test/renderers.tsx) renders the full router with providers and configurable auth state:
import { renderWithFileRoutes } from "@/test/renderers"
// Default: authenticated as test@example.com
await renderWithFileRoutes(<div />, { initialLocation: "/dashboard" })
// Custom auth state
await renderWithFileRoutes(<div />, {
initialLocation: "/login",
routerContext: {
auth: {
isAuthenticated: false,
isLoading: false,
email: null,
userId: null,
login: () => {},
logout: async () => {},
checkAuth: async () => {},
},
},
})MSW handlers are aggregated in src/api/handlers.ts. A default /auth/me handler (returns 401) suppresses warnings during tests.
- Logger (
src/lib/logger.ts) —debug/info/warn/error. Console in dev, structured JSON in prod.VITE_LOG_LEVELcontrols the minimum level. - Analytics (
src/lib/analytics.tsx) —AnalyticsProvider+useAnalytics()hook withtrack/identify/page. Route changes are tracked automatically. - Feature flags (
src/lib/feature-flags.tsx) —FeatureFlagProviderfetches from the API'sGET /flagsendpoint (TanStack Query, refetch on focus). Falls back toVITE_FEATURE_*env vars on failure. UseuseFeatureFlag("name")or<Feature flag="name">.
| Variable | Description | Default |
|---|---|---|
VITE_API_URL |
Backend API URL | /api |
VITE_LOG_LEVEL |
Minimum log level (debug/info/warn/error) | debug (dev), warn (prod) |
VITE_FEATURE_* |
Feature flag overrides (e.g. VITE_FEATURE_NEW_DASHBOARD=true) |
(none) |
OPENAPI_URL |
OpenAPI spec URL (for code generation) | http://localhost:8000/openapi.json |
OPENAPI_URL is only used during development for pnpm generate-api. The generated files are committed.
Apache 2.0 — see LICENSE.
- Vite · TanStack Router · TanStack Query
- shadcn/ui · Tailwind CSS
- Zod · ky · orval · MSW
- Game icons by game-icons.net contributors, licensed under CC-BY 3.0