From aab2c02c2e11a0fecae6066f2515c685231e8c77 Mon Sep 17 00:00:00 2001 From: Lukas Bauer Date: Wed, 7 Jan 2026 10:00:00 +0000 Subject: [PATCH] Initial React/TypeScript frontend setup --- .env.example | 3 +++ .gitignore | 7 +++++++ README.md | 27 +++++++++++++++++++++++++++ package.json | 28 ++++++++++++++++++++++++++++ src/styles/tokens.css | 21 +++++++++++++++++++++ tsconfig.json | 13 +++++++++++++ vite.config.ts | 11 +++++++++++ 7 files changed, 110 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 README.md create mode 100644 package.json create mode 100644 src/styles/tokens.css create mode 100644 tsconfig.json create mode 100644 vite.config.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..d060bfe --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +VITE_API_BASE_URL=http://localhost:8080 +VITE_AUTH_ISSUER=https://auth.nexus.local +VITE_SENTRY_DSN= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..36e11a0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +dist/ +.env.local +.env.*.local +*.log +.DS_Store +coverage/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..6cdb236 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# nexus/frontend + +Nexus web frontend. Built with React + TypeScript + Vite. + +## Development + + npm install + npm run dev # dev server on http://localhost:5173 + npm run build # production build to dist/ + npm run test # unit tests (vitest) + npm run lint # eslint + tsc + +## Structure + +``` +src/ + components/ — reusable UI components + pages/ — route-level page components + hooks/ — custom React hooks + api/ — API client and types + styles/ — global styles and design tokens + utils/ — pure utility functions +``` + +## Environment variables + +Copy `.env.example` to `.env.local` for local development. diff --git a/package.json b/package.json new file mode 100644 index 0000000..8fe43d4 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "nexus-frontend", + "version": "1.4.0", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "test": "vitest", + "lint": "eslint src --ext .ts,.tsx && tsc --noEmit" + }, + "dependencies": { + "react": "^18.3.0", + "react-dom": "^18.3.0", + "react-router-dom": "^6.22.0", + "@tanstack/react-query": "^5.28.0", + "axios": "^1.6.8" + }, + "devDependencies": { + "@types/react": "^18.3.0", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.2.1", + "typescript": "^5.4.3", + "vite": "^5.2.6", + "vitest": "^1.4.0", + "eslint": "^8.57.0", + "@typescript-eslint/eslint-plugin": "^7.4.0" + } +} diff --git a/src/styles/tokens.css b/src/styles/tokens.css new file mode 100644 index 0000000..cabf380 --- /dev/null +++ b/src/styles/tokens.css @@ -0,0 +1,21 @@ +:root { + --color-primary: #0055cc; + --color-primary-hover: #003d99; + --color-surface: #f8f9fa; + --color-surface-raised: #ffffff; + --color-border: #dee2e6; + --color-text: #212529; + --color-text-muted: #6c757d; + --color-error: #dc3545; + --color-success: #198754; + + --font-sans: 'Inter', system-ui, sans-serif; + --font-mono: 'JetBrains Mono', 'Fira Code', monospace; + + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 16px; + + --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08); + --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.12); +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..43fd58c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2020", "DOM"], + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true + }, + "include": ["src"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..04d8960 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + server: { + proxy: { + '/api': 'http://localhost:8080', + }, + }, +});