W0 web foundation: Vite + React SPA under /app/, sync-pull ledger, auth, tokens, shared components
Build Kvitt images / build (push) Failing after 1h14m5s
Build Kvitt images / build (push) Failing after 1h14m5s
web/ is the browser client's scaffold: Vite 8, React 19, TypeScript 5.9 strict, React Router 7 (basename /app, every fixed route with a lazy placeholder page), TanStack Query 5 (refetch on focus and every 60 s), openapi-typescript types generated from contracts/openapi.yaml with openapi-fetch. Reads go through GET /sync (no REST reads exist for the ledger, SPEC §7): useLedger() pulls from cursor 0 and then incrementally, restarting on a new epoch or cursor_ahead. Login pairs the browser as "Web · <browser>" with an invite code (E-3); every call sends the SPEC §14.3.1 headers, a 401 signs out. kvitt-domain's split, balances, allocation and settlement rules are ported to web/src/lib and pass every case of contracts/test-vectors. Design tokens from design-spec §2 in tokens.css (light-dark()), Material Symbols Rounded (Apache-2.0) as generated inline SVG, sv/en catalogs generated from docs/ux/strings.csv plus web-strings.csv. Gate: cd web && npm run check. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
interface PackageJson {
|
||||
version: string;
|
||||
kvitt: { versionCode: number };
|
||||
}
|
||||
|
||||
const pkg = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf-8')) as PackageJson;
|
||||
|
||||
/** API paths of contracts/openapi.yaml; `npm run dev` forwards them to a local kvitt-server (README). */
|
||||
const API_PREFIXES = [
|
||||
'/health',
|
||||
'/setup',
|
||||
'/invites',
|
||||
'/me',
|
||||
'/users',
|
||||
'/devices',
|
||||
'/accounts',
|
||||
'/categories',
|
||||
'/recurring-templates',
|
||||
'/sync',
|
||||
'/settlements',
|
||||
'/apk',
|
||||
];
|
||||
const devApi = process.env.KVITT_DEV_API ?? 'http://localhost:8080';
|
||||
|
||||
export default defineConfig({
|
||||
base: '/app/',
|
||||
plugins: [react()],
|
||||
define: {
|
||||
__KVITT_VERSION_NAME__: JSON.stringify(pkg.version),
|
||||
__KVITT_VERSION_CODE__: JSON.stringify(pkg.kvitt.versionCode),
|
||||
},
|
||||
server: {
|
||||
proxy: Object.fromEntries(API_PREFIXES.map((prefix) => [prefix, { target: devApi, changeOrigin: true }])),
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
sourcemap: false,
|
||||
rolldownOptions: {
|
||||
output: {
|
||||
// Libraries in their own chunks: they change less often than the app, so browsers keep them across deploys.
|
||||
codeSplitting: {
|
||||
groups: [
|
||||
{ name: 'react', test: /node_modules[\\/](react|react-dom|scheduler)[\\/]/ },
|
||||
{ name: 'vendor', test: /node_modules[\\/]/ },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
setupFiles: ['src/test/setup.ts'],
|
||||
include: ['src/**/*.test.{ts,tsx}'],
|
||||
css: { modules: { classNameStrategy: 'non-scoped' } },
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user