fix(arch): Config SSOT, reproducible builds, and data pipeline documentation (#41)
ba32591
unverified
Spec 37.0: Frontend Project Setup
Status: READY FOR IMPLEMENTATION Phase: 0 of 5 Depends On: Spec 36 (Stack Definition) Goal: Scaffold Vite + React + TypeScript project with testing infrastructure
Deliverables
By the end of this phase, you will have:
- Working Vite dev server (
npm run dev) - TypeScript compilation passing (
npx tsc --noEmit) - Vitest running with a smoke test (
npm test) - Tailwind CSS working
- MSW configured for API mocking
Step 1: Create Vite Project
cd /Users/ray/Desktop/CLARITY-DIGITAL-TWIN/stroke-deepisles-demo
npm create vite@latest frontend -- --template react-ts
cd frontend
Step 2: Install Dependencies
# Core dependencies
npm install @niivue/niivue@0.65.0
# Dev dependencies - Testing
npm install -D vitest@2.1.8 @vitest/coverage-v8@2.1.8 @vitest/ui@2.1.8
npm install -D @testing-library/react@16.3.0 @testing-library/jest-dom@6.6.3 @testing-library/user-event@14.5.2
npm install -D jsdom@25.0.1 msw@2.7.0
# Dev dependencies - Styling
npm install -D tailwindcss@4.1.7 @tailwindcss/vite@4.1.7
Step 3: Configure package.json Scripts
Replace scripts section:
{
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"test": "vitest",
"test:ui": "vitest --ui",
"test:coverage": "vitest run --coverage"
}
}
Step 4: Configure Vite + Vitest
Replace vite.config.ts:
/// <reference types="vitest" />
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [react(), tailwindcss()],
build: {
outDir: 'dist',
},
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./src/test/setup.ts'],
include: ['src/**/*.{test,spec}.{ts,tsx}'],
exclude: ['node_modules', 'e2e'],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
include: ['src/**/*.{ts,tsx}'],
exclude: [
'src/**/*.test.{ts,tsx}',
'src/test/**',
'src/mocks/**',
'src/main.tsx',
],
},
},
})
Step 5: Configure TypeScript
Replace tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"types": ["vitest/globals", "@testing-library/jest-dom"]
},
"include": ["src"]
}
Step 6: Configure Tailwind CSS
Replace src/index.css:
@import "tailwindcss";
Step 7: Create Test Setup
Create src/test/setup.ts:
import '@testing-library/jest-dom/vitest'
import { cleanup } from '@testing-library/react'
import { afterEach, beforeAll, afterAll } from 'vitest'
import { server } from '../mocks/server'
// Establish API mocking before all tests
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
// Clean up after each test
afterEach(() => {
cleanup()
server.resetHandlers()
})
// Clean up after all tests
afterAll(() => server.close())
// Mock ResizeObserver (needed for some UI components)
global.ResizeObserver = class ResizeObserver {
observe() {}
unobserve() {}
disconnect() {}
}
Step 8: Create MSW Mocks
Create src/mocks/handlers.ts:
import { http, HttpResponse } from 'msw'
const API_BASE = import.meta.env.VITE_API_URL || 'http://localhost:7860'
export const handlers = [
// GET /api/cases - List available cases
http.get(`${API_BASE}/api/cases`, () => {
return HttpResponse.json({
cases: ['sub-stroke0001', 'sub-stroke0002', 'sub-stroke0003'],
})
}),
// POST /api/segment - Run segmentation
http.post(`${API_BASE}/api/segment`, async ({ request }) => {
const body = (await request.json()) as { case_id: string; fast_mode?: boolean }
return HttpResponse.json({
caseId: body.case_id,
diceScore: 0.847,
volumeMl: 15.32,
elapsedSeconds: body.fast_mode === false ? 45.0 : 12.5,
dwiUrl: `${API_BASE}/files/dwi.nii.gz`,
predictionUrl: `${API_BASE}/files/prediction.nii.gz`,
})
}),
]
Create src/mocks/server.ts:
import { setupServer } from 'msw/node'
import { handlers } from './handlers'
export const server = setupServer(...handlers)
Step 9: Create Smoke Test
Create src/App.test.tsx:
import { describe, it, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
import App from './App'
describe('App', () => {
it('renders without crashing', () => {
render(<App />)
// This will pass with default Vite template
expect(document.body).toBeInTheDocument()
})
})
Step 10: Create Environment File
Create .env:
VITE_API_URL=http://localhost:7860
Create .env.example:
VITE_API_URL=http://localhost:7860
Verification Checklist
Run these commands to verify setup:
# 1. TypeScript compiles
npx tsc --noEmit
# Expected: No errors
# 2. Dev server starts
npm run dev
# Expected: Server at http://localhost:5173
# 3. Tests pass
npm test
# Expected: 1 test passing
# 4. Build works
npm run build
# Expected: dist/ folder created
File Structure After This Phase
frontend/
βββ src/
β βββ mocks/
β β βββ handlers.ts
β β βββ server.ts
β βββ test/
β β βββ setup.ts
β βββ App.tsx
β βββ App.test.tsx
β βββ main.tsx
β βββ index.css
βββ .env
βββ .env.example
βββ index.html
βββ package.json
βββ tsconfig.json
βββ vite.config.ts
Next Phase
Once verification passes, proceed to Spec 37.1: Foundation Components