diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs
new file mode 100644
index 0000000..aa191ed
--- /dev/null
+++ b/frontend/.eslintrc.cjs
@@ -0,0 +1,20 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:react-hooks/recommended',
+ ],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parser: '@typescript-eslint/parser',
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ '@typescript-eslint/no-explicit-any': 'warn',
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
+ },
+}
diff --git a/frontend/index.html b/frontend/index.html
new file mode 100644
index 0000000..2c37546
--- /dev/null
+++ b/frontend/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ VictoriaLogs Manager
+
+
+
+
+
+
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 0000000..ca8cf5d
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "victorialogs-manager-frontend",
+ "private": true,
+ "version": "1.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "preview": "vite preview",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
+ },
+ "dependencies": {
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-router-dom": "^6.21.3",
+ "zustand": "^4.5.0",
+ "axios": "^1.6.5",
+ "echarts": "^5.4.3",
+ "echarts-for-react": "^3.0.2",
+ "@monaco-editor/react": "^4.6.0",
+ "react-window": "^1.8.10"
+ },
+ "devDependencies": {
+ "@types/react": "^18.2.48",
+ "@types/react-dom": "^18.2.18",
+ "@types/react-window": "^1.8.8",
+ "@typescript-eslint/eslint-plugin": "^6.19.0",
+ "@typescript-eslint/parser": "^6.19.0",
+ "@vitejs/plugin-react": "^4.2.1",
+ "autoprefixer": "^10.4.17",
+ "eslint": "^8.56.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.5",
+ "postcss": "^8.4.33",
+ "tailwindcss": "^3.4.1",
+ "typescript": "^5.3.3",
+ "vite": "^5.0.11"
+ }
+}
diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js
new file mode 100644
index 0000000..2e7af2b
--- /dev/null
+++ b/frontend/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
new file mode 100644
index 0000000..383d821
--- /dev/null
+++ b/frontend/src/App.tsx
@@ -0,0 +1,37 @@
+import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'
+import Login from './pages/Login'
+import Dashboard from './pages/Dashboard'
+import LogsExplorer from './pages/LogsExplorer'
+import AlertsManager from './pages/AlertsManager'
+import PatternDetection from './pages/PatternDetection'
+import Reports from './pages/Reports'
+import Settings from './pages/Settings'
+import Layout from './components/common/Layout'
+import ProtectedRoute from './components/common/ProtectedRoute'
+
+function App() {
+ return (
+
+
+ {/* Public routes */}
+ } />
+
+ {/* Protected routes */}
+ }>
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+ {/* 404 */}
+ } />
+
+
+ )
+}
+
+export default App
diff --git a/frontend/src/components/common/Layout.tsx b/frontend/src/components/common/Layout.tsx
new file mode 100644
index 0000000..e5f3292
--- /dev/null
+++ b/frontend/src/components/common/Layout.tsx
@@ -0,0 +1,69 @@
+import { Outlet, Link, useLocation } from 'react-router-dom'
+
+export default function Layout() {
+ const location = useLocation()
+
+ const navigation = [
+ { name: 'Dashboard', path: '/dashboard', icon: '📊' },
+ { name: 'Logs Explorer', path: '/logs', icon: '🔍' },
+ { name: 'Alerts', path: '/alerts', icon: '🔔' },
+ { name: 'Patterns', path: '/patterns', icon: '🎯' },
+ { name: 'Reports', path: '/reports', icon: '📈' },
+ { name: 'Settings', path: '/settings', icon: '⚙️' },
+ ]
+
+ return (
+
+ {/* Sidebar */}
+
+
+ {/* Logo */}
+
+
VictoriaLogs
+
+
+ {/* Navigation */}
+
+
+ {/* User info */}
+
+
+
+ A
+
+
+
Admin User
+
admin@example.com
+
+
+
+
+
+
+ {/* Main content */}
+
+
+ )
+}
diff --git a/frontend/src/components/common/ProtectedRoute.tsx b/frontend/src/components/common/ProtectedRoute.tsx
new file mode 100644
index 0000000..f78f87c
--- /dev/null
+++ b/frontend/src/components/common/ProtectedRoute.tsx
@@ -0,0 +1,17 @@
+import { ReactNode } from 'react'
+import { Navigate } from 'react-router-dom'
+
+interface ProtectedRouteProps {
+ children: ReactNode
+}
+
+export default function ProtectedRoute({ children }: ProtectedRouteProps) {
+ // TODO: Implement actual authentication check
+ const isAuthenticated = true // Temporary - always allow access
+
+ if (!isAuthenticated) {
+ return
+ }
+
+ return <>{children}>
+}
diff --git a/frontend/src/index.css b/frontend/src/index.css
new file mode 100644
index 0000000..c0cee62
--- /dev/null
+++ b/frontend/src/index.css
@@ -0,0 +1,62 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+#root {
+ width: 100%;
+ min-height: 100vh;
+}
+
+@layer base {
+ * {
+ @apply border-border;
+ }
+ body {
+ @apply bg-gray-50 text-gray-900;
+ }
+}
+
+@layer components {
+ .btn {
+ @apply px-4 py-2 rounded-lg font-medium transition-colors;
+ }
+
+ .btn-primary {
+ @apply bg-primary-600 text-white hover:bg-primary-700;
+ }
+
+ .btn-secondary {
+ @apply bg-gray-200 text-gray-800 hover:bg-gray-300;
+ }
+
+ .input {
+ @apply w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent;
+ }
+
+ .card {
+ @apply bg-white rounded-lg shadow-md p-6;
+ }
+}
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
new file mode 100644
index 0000000..964aeb4
--- /dev/null
+++ b/frontend/src/main.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App'
+import './index.css'
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/frontend/src/pages/AlertsManager.tsx b/frontend/src/pages/AlertsManager.tsx
new file mode 100644
index 0000000..fd1376e
--- /dev/null
+++ b/frontend/src/pages/AlertsManager.tsx
@@ -0,0 +1,8 @@
+export default function AlertsManager() {
+ return (
+
+
Alerts Manager
+
Alerts Manager page - To be implemented
+
+ )
+}
diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx
new file mode 100644
index 0000000..7d5e096
--- /dev/null
+++ b/frontend/src/pages/Dashboard.tsx
@@ -0,0 +1,8 @@
+export default function Dashboard() {
+ return (
+
+
Dashboard
+
Dashboard page - To be implemented
+
+ )
+}
diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx
new file mode 100644
index 0000000..1a4acf2
--- /dev/null
+++ b/frontend/src/pages/Login.tsx
@@ -0,0 +1,10 @@
+export default function Login() {
+ return (
+
+
+
VictoriaLogs Manager
+
Login page - To be implemented
+
+
+ )
+}
diff --git a/frontend/src/pages/LogsExplorer.tsx b/frontend/src/pages/LogsExplorer.tsx
new file mode 100644
index 0000000..d6e8e3e
--- /dev/null
+++ b/frontend/src/pages/LogsExplorer.tsx
@@ -0,0 +1,8 @@
+export default function LogsExplorer() {
+ return (
+
+
Logs Explorer
+
Logs Explorer page - To be implemented
+
+ )
+}
diff --git a/frontend/src/pages/PatternDetection.tsx b/frontend/src/pages/PatternDetection.tsx
new file mode 100644
index 0000000..18b8e25
--- /dev/null
+++ b/frontend/src/pages/PatternDetection.tsx
@@ -0,0 +1,8 @@
+export default function PatternDetection() {
+ return (
+
+
Pattern Detection
+
Pattern Detection page - To be implemented
+
+ )
+}
diff --git a/frontend/src/pages/Reports.tsx b/frontend/src/pages/Reports.tsx
new file mode 100644
index 0000000..5c1f8c5
--- /dev/null
+++ b/frontend/src/pages/Reports.tsx
@@ -0,0 +1,8 @@
+export default function Reports() {
+ return (
+
+
Reports & Dashboards
+
Reports page - To be implemented
+
+ )
+}
diff --git a/frontend/src/pages/Settings.tsx b/frontend/src/pages/Settings.tsx
new file mode 100644
index 0000000..3e3dcd8
--- /dev/null
+++ b/frontend/src/pages/Settings.tsx
@@ -0,0 +1,8 @@
+export default function Settings() {
+ return (
+
+
Settings
+
Settings page - To be implemented
+
+ )
+}
diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts
new file mode 100644
index 0000000..0cdb10b
--- /dev/null
+++ b/frontend/src/types/index.ts
@@ -0,0 +1,32 @@
+// Common types and interfaces
+
+export interface User {
+ id: string
+ username: string
+ email: string
+ role: 'admin' | 'editor' | 'analyst' | 'viewer'
+ isActive: boolean
+ createdAt: string
+}
+
+export interface AuthResponse {
+ token: string
+ refreshToken: string
+ user: User
+}
+
+export interface ApiError {
+ message: string
+ code?: string
+ details?: unknown
+}
+
+export type Permission =
+ | 'logs:view'
+ | 'logs:export'
+ | 'alerts:manage'
+ | 'alerts:view'
+ | 'patterns:manage'
+ | 'patterns:ml'
+ | 'reports:manage'
+ | 'users:manage'
diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts
new file mode 100644
index 0000000..8ab4f00
--- /dev/null
+++ b/frontend/src/vite-env.d.ts
@@ -0,0 +1,9 @@
+///
+
+interface ImportMetaEnv {
+ readonly VITE_API_BASE_URL: string
+}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv
+}
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
new file mode 100644
index 0000000..744256b
--- /dev/null
+++ b/frontend/tailwind.config.js
@@ -0,0 +1,26 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: [
+ "./index.html",
+ "./src/**/*.{js,ts,jsx,tsx}",
+ ],
+ theme: {
+ extend: {
+ colors: {
+ primary: {
+ 50: '#f0f9ff',
+ 100: '#e0f2fe',
+ 200: '#bae6fd',
+ 300: '#7dd3fc',
+ 400: '#38bdf8',
+ 500: '#0ea5e9',
+ 600: '#0284c7',
+ 700: '#0369a1',
+ 800: '#075985',
+ 900: '#0c4a6e',
+ },
+ },
+ },
+ },
+ plugins: [],
+}
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
new file mode 100644
index 0000000..99cb341
--- /dev/null
+++ b/frontend/tsconfig.json
@@ -0,0 +1,31 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+
+ /* Path aliases */
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["src/*"]
+ }
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json
new file mode 100644
index 0000000..42872c5
--- /dev/null
+++ b/frontend/tsconfig.node.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
new file mode 100644
index 0000000..283fb4d
--- /dev/null
+++ b/frontend/vite.config.ts
@@ -0,0 +1,21 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ server: {
+ port: 3000,
+ host: true,
+ proxy: {
+ '/api': {
+ target: 'http://localhost:8080',
+ changeOrigin: true,
+ }
+ }
+ },
+ build: {
+ outDir: 'dist',
+ sourcemap: true,
+ }
+})