Merge branch 'Features/Frontend/Frontend-Hardening'

This commit is contained in:
MangoPig
2026-06-14 15:23:31 +01:00
8 changed files with 118 additions and 60 deletions

View File

@@ -11,19 +11,21 @@
"scripts": {
"dev": "vite dev",
"build": "vite build",
"start": "vite start",
"typecheck": "tsc --noEmit",
"start": "vite preview",
"preview": "vite preview"
},
"dependencies": {
"lucide-solid": "^0.542.0",
"@solidjs/start": "2.0.0-alpha.2",
"@solidjs/vite-plugin-nitro-2": "^0.1.0",
"lucide-solid": "^0.542.0",
"postcss": "^8.5.15",
"sass": "^1.101.0",
"solid-js": "^1.9.5",
"vite": "^7.0.0"
},
"devDependencies": {
"@types/node": "^25.9.3",
"autoprefixer": "^10.5.0",
"cssnano": "^8.0.2",
"postcss-preset-env": "^11.3.0",

View File

@@ -10,10 +10,10 @@ importers:
dependencies:
'@solidjs/start':
specifier: 2.0.0-alpha.2
version: 2.0.0-alpha.2(crossws@0.4.4(srvx@0.11.8))(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
version: 2.0.0-alpha.2(crossws@0.4.4(srvx@0.11.8))(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
'@solidjs/vite-plugin-nitro-2':
specifier: ^0.1.0
version: 0.1.0(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
version: 0.1.0(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
lucide-solid:
specifier: ^0.542.0
version: 0.542.0(solid-js@1.9.11)
@@ -28,8 +28,11 @@ importers:
version: 1.9.11
vite:
specifier: ^7.0.0
version: 7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
version: 7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
devDependencies:
'@types/node':
specifier: ^25.9.3
version: 25.9.3
autoprefixer:
specifier: ^10.5.0
version: 10.5.0(postcss@8.5.15)
@@ -1262,6 +1265,9 @@ packages:
'@types/micromatch@4.0.10':
resolution: {integrity: sha512-5jOhFDElqr4DKTrTEbnW8DZ4Hz5LRUEmyrGpCMrD/NphYv3nUnaF08xmSLx1rGGnyEs/kFnhiw6dCgcDqMr5PQ==}
'@types/node@25.9.3':
resolution: {integrity: sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==}
'@types/resolve@1.20.2':
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
@@ -3217,6 +3223,9 @@ packages:
unctx@2.5.0:
resolution: {integrity: sha512-p+Rz9x0R7X+CYDkT+Xg8/GhpcShTlU8n+cf9OtOEf7zEQsNcCZO1dPKNRDqvUTaq+P32PMMkxWHwfrxkqfqAYg==}
undici-types@7.24.6:
resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==}
unenv@2.0.0-rc.24:
resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==}
@@ -4476,13 +4485,13 @@ snapshots:
dependencies:
solid-js: 1.9.11
'@solidjs/start@2.0.0-alpha.2(crossws@0.4.4(srvx@0.11.8))(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))':
'@solidjs/start@2.0.0-alpha.2(crossws@0.4.4(srvx@0.11.8))(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))':
dependencies:
'@babel/core': 7.29.0
'@babel/traverse': 7.29.0
'@babel/types': 7.29.0
'@solidjs/meta': 0.29.4(solid-js@1.9.11)
'@tanstack/server-functions-plugin': 1.134.5(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
'@tanstack/server-functions-plugin': 1.134.5(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
'@types/babel__traverse': 7.28.0
'@types/micromatch': 4.0.10
cookie-es: 2.0.0
@@ -4504,17 +4513,17 @@ snapshots:
source-map-js: 1.2.1
srvx: 0.9.8
terracotta: 1.1.0(solid-js@1.9.11)
vite: 7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
vite-plugin-solid: 2.11.10(solid-js@1.9.11)(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
vite: 7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
vite-plugin-solid: 2.11.10(solid-js@1.9.11)(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
transitivePeerDependencies:
- '@testing-library/jest-dom'
- crossws
- supports-color
'@solidjs/vite-plugin-nitro-2@0.1.0(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))':
'@solidjs/vite-plugin-nitro-2@0.1.0(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))':
dependencies:
nitropack: 2.13.1
vite: 7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
vite: 7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
transitivePeerDependencies:
- '@azure/app-configuration'
- '@azure/cosmos'
@@ -4549,7 +4558,7 @@ snapshots:
'@speed-highlight/core@1.2.14': {}
'@tanstack/directive-functions-plugin@1.134.5(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))':
'@tanstack/directive-functions-plugin@1.134.5(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))':
dependencies:
'@babel/code-frame': 7.27.1
'@babel/core': 7.29.0
@@ -4559,7 +4568,7 @@ snapshots:
babel-dead-code-elimination: 1.0.12
pathe: 2.0.3
tiny-invariant: 1.3.3
vite: 7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
vite: 7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
transitivePeerDependencies:
- supports-color
@@ -4576,7 +4585,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@tanstack/server-functions-plugin@1.134.5(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))':
'@tanstack/server-functions-plugin@1.134.5(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))':
dependencies:
'@babel/code-frame': 7.27.1
'@babel/core': 7.29.0
@@ -4585,7 +4594,7 @@ snapshots:
'@babel/template': 7.28.6
'@babel/traverse': 7.29.0
'@babel/types': 7.29.0
'@tanstack/directive-functions-plugin': 1.134.5(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
'@tanstack/directive-functions-plugin': 1.134.5(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
babel-dead-code-elimination: 1.0.12
tiny-invariant: 1.3.3
transitivePeerDependencies:
@@ -4629,6 +4638,10 @@ snapshots:
dependencies:
'@types/braces': 3.0.5
'@types/node@25.9.3':
dependencies:
undici-types: 7.24.6
'@types/resolve@1.20.2': {}
'@types/unist@3.0.3': {}
@@ -6753,6 +6766,8 @@ snapshots:
magic-string: 0.30.21
unplugin: 2.3.11
undici-types@7.24.6: {}
unenv@2.0.0-rc.24:
dependencies:
pathe: 2.0.3
@@ -6876,7 +6891,7 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
vite-plugin-solid@2.11.10(solid-js@1.9.11)(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)):
vite-plugin-solid@2.11.10(solid-js@1.9.11)(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)):
dependencies:
'@babel/core': 7.29.0
'@types/babel__core': 7.20.5
@@ -6884,12 +6899,12 @@ snapshots:
merge-anything: 5.1.7
solid-js: 1.9.11
solid-refresh: 0.6.3(solid-js@1.9.11)
vite: 7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
vitefu: 1.1.2(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
vite: 7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
vitefu: 1.1.2(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0))
transitivePeerDependencies:
- supports-color
vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0):
vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0):
dependencies:
esbuild: 0.27.3
fdir: 6.5.0(picomatch@4.0.3)
@@ -6898,15 +6913,16 @@ snapshots:
rollup: 4.59.0
tinyglobby: 0.2.15
optionalDependencies:
'@types/node': 25.9.3
fsevents: 2.3.3
jiti: 2.6.1
sass: 1.101.0
sass-embedded: 1.100.0
terser: 5.46.0
vitefu@1.1.2(vite@7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)):
vitefu@1.1.2(vite@7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)):
optionalDependencies:
vite: 7.3.1(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
vite: 7.3.1(@types/node@25.9.3)(jiti@2.6.1)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.46.0)
webidl-conversions@3.0.1: {}

View File

@@ -1,4 +1,21 @@
// Path: Frontend/src/entry-client.tsx
// @refresh reload
import type { JSX } from "solid-js";
import { mount, StartClient } from "@solidjs/start/client";
mount(() => <StartClient />, document.getElementById("app")!);
const getAppRoot = (): HTMLElement => {
const appRoot = document.getElementById("app");
if (!(appRoot instanceof HTMLElement)) {
throw new Error("App root element '#app' was not found.");
}
return appRoot;
};
const mountApp = (): void => {
mount((): JSX.Element => <StartClient />, getAppRoot());
};
mountApp();

View File

@@ -1,6 +1,7 @@
// Path: Frontend/src/entry-server.tsx
// @refresh reload
import type { JSX } from "solid-js";
import { createHandler, StartServer } from "@solidjs/start/server";
const themeBootstrapScript = `
@@ -19,22 +20,32 @@ const themeBootstrapScript = `
})();
`;
export default createHandler(() => (
<StartServer
document={({ assets, children, scripts }) => (
<html lang="en" data-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
<script innerHTML={themeBootstrapScript} />
{assets}
</head>
<body>
<div id="app">{children}</div>
{scripts}
</body>
</html>
)}
/>
));
type DocumentRenderProps = {
assets?: JSX.Element;
children?: JSX.Element;
scripts?: JSX.Element;
};
const renderDocument = ({ assets, children, scripts }: DocumentRenderProps): JSX.Element => {
return (
<html lang="en" data-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
<script innerHTML={themeBootstrapScript} />
{assets}
</head>
<body>
<div id="app">{children}</div>
{scripts}
</body>
</html>
);
};
const serverHandler = createHandler((): JSX.Element => {
return <StartServer document={renderDocument} />;
});
export default serverHandler;

View File

@@ -1 +1,3 @@
// Path: Frontend/src/global.d.ts
/// <reference types="@solidjs/start/env" />

View File

@@ -16,7 +16,7 @@ export const resolvePreferredTheme = (): Theme => {
export const getDocumentTheme = (): Theme => (document.documentElement.getAttribute("data-theme") === "dark" ? "dark" : "light");
export const setTheme = (theme: Theme) => {
export const setTheme = (theme: Theme): void => {
document.documentElement.setAttribute("data-theme", theme);
localStorage.setItem(THEME_STORAGE_KEY, theme);
};

View File

@@ -1,3 +1,11 @@
// Path: Frontend/src/lib/icons/index.ts
export { Bell, Check, ChevronDown, ChevronLeft, ChevronRight, Folder, FolderOpen, Home, LayoutGrid, MoreHorizontal, Plus, Search, Settings, User, X } from "lucide-solid";
export { default as Bell } from "lucide-solid/icons/bell";
export { default as ChevronDown } from "lucide-solid/icons/chevron-down";
export { default as Folder } from "lucide-solid/icons/folder";
export { default as Home } from "lucide-solid/icons/house";
export { default as LayoutGrid } from "lucide-solid/icons/layout-grid";
export { default as Plus } from "lucide-solid/icons/plus";
export { default as Search } from "lucide-solid/icons/search";
export { default as Settings } from "lucide-solid/icons/settings";
export { default as User } from "lucide-solid/icons/user";

View File

@@ -1,19 +1,21 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"jsx": "preserve",
"jsxImportSource": "solid-js",
"allowJs": true,
"strict": true,
"noEmit": true,
"types": ["vite/client"],
"isolatedModules": true,
"paths": {
"~/*": ["./src/*"]
}
}
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"jsx": "preserve",
"jsxImportSource": "solid-js",
"allowJs": true,
"strict": true,
"skipLibCheck": true,
"noEmit": true,
"types": ["vite/client", "node"],
"isolatedModules": true,
"paths": {
"~/*": ["./src/*"]
}
}
}