Add JWT authentication, fantasy-themed UI, and full game client

Auth: login/register page, Bearer token via apiFetch wrapper, 401
redirect to login, logout button, localStorage token persistence.

Pages: Home (dashboard, char creation, review board), Training Yard,
Garth's Shop, Temple, Inventory, Adventure (zone selection, combat log),
Songs (bard-only), Spells (caster-only), Item Catalogue (admin-only).

Features: 15s regen polling (HP/nerve/energy), energy/nerve bars, gold
display, equipment slot grid, item quality color coding, stat pills,
crit severity highlighting, XP progress bar, shop buy/sell filters.
This commit is contained in:
Jan-Peter von Hunnius 2026-08-09 17:01:37 +02:00
parent ee7c6f7d4f
commit 5142f18b1b
6 changed files with 1334 additions and 4 deletions

View file

@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>skara-brae-client</title> <title>Skara Brae</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

9
package-lock.json generated
View file

@ -8,6 +8,7 @@
"name": "skara-brae-client", "name": "skara-brae-client",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@lucide/vue": "^1.28.0",
"pinia": "^4.0.2", "pinia": "^4.0.2",
"vue": "^3.5.40" "vue": "^3.5.40"
}, },
@ -98,6 +99,14 @@
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="
}, },
"node_modules/@lucide/vue": {
"version": "1.28.0",
"resolved": "https://registry.npmjs.org/@lucide/vue/-/vue-1.28.0.tgz",
"integrity": "sha512-cO89UyNM/0i2Srdi04nFWeEOQkqzDZlM2ehtWyBhcMpRTJDKpMZPCGAVlmVBgBgr5HaeL5L6FsU8RHsOdwXtKw==",
"peerDependencies": {
"vue": ">=3.0.1"
}
},
"node_modules/@napi-rs/wasm-runtime": { "node_modules/@napi-rs/wasm-runtime": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz",

View file

@ -9,6 +9,7 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@lucide/vue": "^1.28.0",
"pinia": "^4.0.2", "pinia": "^4.0.2",
"vue": "^3.5.40" "vue": "^3.5.40"
}, },

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

File diff suppressed because it is too large Load diff

View file

@ -4,4 +4,12 @@ import vue from '@vitejs/plugin-vue'
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue()],
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
},
},
},
}) })