✨ feat(frontend): scaffold minimal Nuxt 3 frontend with healthz dashboard
First step toward a Vue 3 / Nuxt 3 / Playwright e2e frontend stack. Adds: - frontend/ - Nuxt 3 scaffold (TypeScript) - frontend/components/HealthDashboard.vue - calls /api/healthz, shows status/version/uptime/timestamp - frontend/pages/index.vue - landing page using HealthDashboard - frontend/nuxt.config.ts - dev proxy /api -> http://localhost:8080 - frontend/playwright.config.ts + tests/e2e/health.spec.ts - 1 baseline e2e test - .gitignore - frontend artifacts excluded Out of scope (separate PRs): - Storybook - Design system / Tailwind - Auth pages - Production build / deploy config Generated ~95% in autonomy by Mistral Vibe via ICM workspace ~/Work/Vibe/workspaces/frontend-nuxt-scaffold/. Trainer (Claude) finalized commit/PR (Mistral hit max-turns or trainer takeover). 🤖 Co-Authored-By: Mistral Vibe (devstral-2 / mistral-medium-3.5) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
10
.gitignore
vendored
10
.gitignore
vendored
@@ -34,3 +34,13 @@ config/runner
|
||||
coverage.txt
|
||||
trigger.txt
|
||||
test_trigger.txt
|
||||
|
||||
# Frontend
|
||||
frontend/node_modules/
|
||||
frontend/.nuxt/
|
||||
frontend/.output/
|
||||
frontend/dist/
|
||||
frontend/.env
|
||||
frontend/.cache/
|
||||
frontend/test-results/
|
||||
frontend/playwright-report/
|
||||
|
||||
3
frontend/app.vue
Normal file
3
frontend/app.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<NuxtPage />
|
||||
</template>
|
||||
22
frontend/components/HealthDashboard.vue
Normal file
22
frontend/components/HealthDashboard.vue
Normal file
@@ -0,0 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
interface HealthInfo {
|
||||
status: string
|
||||
version: string
|
||||
uptime_seconds: number
|
||||
timestamp: string
|
||||
}
|
||||
const { data, pending, error } = await useFetch<HealthInfo>('/api/healthz')
|
||||
</script>
|
||||
<template>
|
||||
<section data-testid="health-dashboard">
|
||||
<h2>Server Health</h2>
|
||||
<p v-if="pending">Loading...</p>
|
||||
<p v-else-if="error">Error loading health: {{ error.message }}</p>
|
||||
<ul v-else-if="data" data-testid="health-info">
|
||||
<li><strong>Status:</strong> <span data-testid="health-status">{{ data.status }}</span></li>
|
||||
<li><strong>Version:</strong> {{ data.version }}</li>
|
||||
<li><strong>Uptime:</strong> {{ data.uptime_seconds }} seconds</li>
|
||||
<li><strong>Last check:</strong> {{ data.timestamp }}</li>
|
||||
</ul>
|
||||
</section>
|
||||
</template>
|
||||
11
frontend/nuxt.config.ts
Normal file
11
frontend/nuxt.config.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export default defineNuxtConfig({
|
||||
devtools: { enabled: true },
|
||||
nitro: {
|
||||
devProxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8080',
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
11237
frontend/package-lock.json
generated
Normal file
11237
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
frontend/package.json
Normal file
18
frontend/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "dance-lessons-coach-frontend",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@types/node": "^25.6.0",
|
||||
"nuxt": "^3.13.0",
|
||||
"typescript": "^6.0.3"
|
||||
},
|
||||
"packageManager": "npm@11.5.2"
|
||||
}
|
||||
6
frontend/pages/index.vue
Normal file
6
frontend/pages/index.vue
Normal file
@@ -0,0 +1,6 @@
|
||||
<template>
|
||||
<main>
|
||||
<h1>dance-lessons-coach</h1>
|
||||
<HealthDashboard />
|
||||
</main>
|
||||
</template>
|
||||
14
frontend/playwright.config.ts
Normal file
14
frontend/playwright.config.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { defineConfig } from '@playwright/test'
|
||||
export default defineConfig({
|
||||
testDir: './tests/e2e',
|
||||
timeout: 30_000,
|
||||
use: {
|
||||
baseURL: 'http://localhost:3000',
|
||||
},
|
||||
webServer: {
|
||||
command: 'npm run dev',
|
||||
url: 'http://localhost:3000',
|
||||
timeout: 60_000,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
},
|
||||
})
|
||||
8
frontend/tests/e2e/health.spec.ts
Normal file
8
frontend/tests/e2e/health.spec.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test('home page loads and shows server health info', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
await expect(page.getByTestId('health-dashboard')).toBeVisible()
|
||||
const heading = page.getByRole('heading', { name: /dance-lessons-coach/i })
|
||||
await expect(heading).toBeVisible()
|
||||
})
|
||||
6
frontend/tsconfig.json
Normal file
6
frontend/tsconfig.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "./.nuxt/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"strict": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user