From 99878bae4c620f1b1bcf43c165508871e111e87f Mon Sep 17 00:00:00 2001 From: dev-agent Date: Tue, 28 Apr 2026 16:06:16 +0000 Subject: [PATCH] chore: bootstrap devopspanel scaffold --- .gitignore | 5 +++ README.md | 37 ++++++++++++++++++ eslint.config.js | 25 +++++++++++++ index.html | 12 ++++++ package.json | 29 +++++++++++++++ src/App.css | 93 ++++++++++++++++++++++++++++++++++++++++++++++ src/App.tsx | 48 ++++++++++++++++++++++++ src/index.css | 15 ++++++++ src/main.tsx | 10 +++++ tsconfig.app.json | 22 +++++++++++ tsconfig.json | 7 ++++ tsconfig.node.json | 16 ++++++++ vite.config.ts | 6 +++ 13 files changed, 325 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 eslint.config.js create mode 100644 index.html create mode 100644 package.json create mode 100644 src/App.css create mode 100644 src/App.tsx create mode 100644 src/index.css create mode 100644 src/main.tsx create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b5f5e59 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules +dist +.vite +.DS_Store +*.tsbuildinfo diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec26e75 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# devopspanel + +Baseline scaffold for the DevOps orchestration admin panel. + +## Baseline stack choice +- Existing Mission Control backend runtime +- React 19 +- TypeScript +- Vite 7 +- OpenAPI-first typed integration in the next slices + +## Setup +```bash +npm install +``` + +## Run +```bash +npm run dev +``` +Application defaults to `http://localhost:5173`. + +## Quality checks +```bash +npm run build +npm run lint +``` + +## Current scope +- Minimal frontend shell only. +- No live API wiring in the baseline commit. +- `environment summary` stays mock-only until a worker-visible route exists in the current backend runtime. + +## Next development slice +1. Add app shell sections for `timeline`, `audit feed`, and `environment summary`. +2. Introduce typed DTO/fixture layer from the approved first-slice contracts. +3. Keep `environment summary` behind mock data until the live route is available. diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..05c6758 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,25 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], + }, + }, +) diff --git a/index.html b/index.html new file mode 100644 index 0000000..c207f96 --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + + + devopspanel + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..19d728c --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "devopspanel", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1" + }, + "devDependencies": { + "@eslint/js": "^9.31.0", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react": "^5.0.0", + "eslint": "^9.31.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^16.3.0", + "typescript": "~5.8.3", + "typescript-eslint": "^8.37.0", + "vite": "^7.0.4" + } +} diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..6f16b54 --- /dev/null +++ b/src/App.css @@ -0,0 +1,93 @@ +:root { + color: #e5eef7; + background: #0b1220; + font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; +} + +body { + margin: 0; + min-width: 320px; + min-height: 100vh; + background: + radial-gradient(circle at top, rgba(56, 189, 248, 0.18), transparent 35%), + linear-gradient(180deg, #020617 0%, #0f172a 100%); +} + +#root { + min-height: 100vh; +} + +.app-shell { + max-width: 1120px; + margin: 0 auto; + padding: 48px 24px 64px; +} + +.hero-card, +.next-slice-card, +.status-grid article { + background: rgba(15, 23, 42, 0.8); + border: 1px solid rgba(148, 163, 184, 0.18); + border-radius: 24px; + box-shadow: 0 20px 45px rgba(2, 6, 23, 0.35); +} + +.hero-card, +.next-slice-card { + padding: 28px; +} + +.eyebrow { + margin: 0 0 12px; + text-transform: uppercase; + letter-spacing: 0.12em; + font-size: 0.8rem; + color: #38bdf8; +} + +h1, +h2, +p, +ul { + margin-top: 0; +} + +h1 { + font-size: clamp(2.4rem, 5vw, 4rem); + margin-bottom: 16px; +} + +.lede { + font-size: 1.1rem; + line-height: 1.7; + max-width: 68ch; + color: #cbd5e1; +} + +.status-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 20px; + margin: 28px 0; +} + +.status-grid article { + padding: 22px; +} + +.status-grid h2, +.next-slice-card h2 { + margin-bottom: 12px; + font-size: 1.1rem; +} + +.status-grid p, +.next-slice-card li { + color: #cbd5e1; + line-height: 1.6; +} + +.next-slice-card ul { + padding-left: 20px; + margin-bottom: 0; +} diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..1458746 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,48 @@ +import './App.css' + +const nextSlice = [ + 'Timeline block wired to approved DTO fixtures', + 'Audit feed block wired to approved DTO fixtures', + 'Environment summary placeholder kept mock-only', +] + +function App() { + return ( +
+
+

Mission Control / devopspanel

+

DevOps orchestration admin panel

+

+ Baseline frontend scaffold for the first implementation slice. This commit + intentionally sets the stack and shell contract before live integrations. +

+
+ +
+
+

Baseline stack

+

React + TypeScript + Vite

+
+
+

Current state

+

Scaffold only, no runtime data wiring yet

+
+
+

Guardrail

+

Environment summary remains mock-only until live worker-visible route exists

+
+
+ +
+

Next development slice

+
    + {nextSlice.map((item) => ( +
  • {item}
  • + ))} +
+
+
+ ) +} + +export default App diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..b54564a --- /dev/null +++ b/src/index.css @@ -0,0 +1,15 @@ +html { + color-scheme: dark; +} + +body { + margin: 0; +} + +* { + box-sizing: border-box; +} + +a { + color: inherit; +} diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 0000000..db032b7 --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..12047cc --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..894eace --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "noEmit": true, + "strict": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..9ffcc67 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], +})