Spaces:
Running
Running
| # Frontend Scaffold & Recommendations | |
| ## π¨ Recommended Tech Stack | |
| ``` | |
| Next.js 14 | |
| βββ React 18 | |
| βββ TypeScript | |
| βββ Tailwind CSS | |
| βββ React Flow (for reasoning graphs) | |
| βββ Axios (API client) | |
| ``` | |
| --- | |
| ## π Suggested Project Structure | |
| ``` | |
| frontend/ | |
| βββ public/ | |
| β βββ assets/ | |
| βββ src/ | |
| β βββ app/ | |
| β β βββ layout.tsx # Root layout | |
| β β βββ page.tsx # Home page | |
| β β βββ upload/ | |
| β β β βββ page.tsx # Paper upload | |
| β β βββ analysis/ | |
| β β β βββ page.tsx # Analysis dashboard | |
| β β β βββ [id]/ | |
| β β β βββ page.tsx # Analysis details | |
| β β βββ protocols/ | |
| β β β βββ [id]/ | |
| β β β βββ page.tsx # Protocol view/edit | |
| β β βββ admin/ | |
| β β βββ page.tsx # Admin panel | |
| β βββ components/ | |
| β β βββ ui/ # Reusable UI | |
| β β β βββ Button.tsx | |
| β β β βββ Card.tsx | |
| β β β βββ Modal.tsx | |
| β β β βββ layout/ | |
| β β βββ features/ # Feature components | |
| β β β βββ UploadZone.tsx | |
| β β β βββ ContradictionView.tsx | |
| β β β βββ ProtocolEditor.tsx | |
| β β β βββ ReasoningTracer.tsx | |
| β β β βββ GraphVisualizer.tsx | |
| β β βββ layout/ | |
| β β βββ Header.tsx | |
| β β βββ Sidebar.tsx | |
| β β βββ Footer.tsx | |
| β βββ lib/ | |
| β β βββ api/ | |
| β β β βββ client.ts # Axios instance | |
| β β β βββ endpoints.ts # API URLs | |
| β β β βββ types.ts # TypeScript interfaces | |
| β β βββ hooks/ | |
| β β β βββ useAnalysis.ts | |
| β β β βββ usePapers.ts | |
| β β β βββ useProtocols.ts | |
| β β βββ utils/ | |
| β β βββ formatting.ts | |
| β β βββ validation.ts | |
| β βββ store/ # Zustand or Redux | |
| β β βββ analysisStore.ts | |
| β β βββ userStore.ts | |
| β βββ styles/ | |
| β β βββ globals.css # Tailwind imports | |
| β βββ types/ | |
| β βββ analysis.ts | |
| β βββ protocol.ts | |
| β βββ paper.ts | |
| βββ package.json | |
| βββ tsconfig.json | |
| ``` | |
| --- | |
| ## π Getting Started | |
| ### 1. Create New Next.js Project | |
| ```bash | |
| # Using create-next-app | |
| npx create-next-app@latest scoinvestigator-frontend \ | |
| --typescript \ | |
| --tailwind \ | |
| --eslint | |
| cd scoinvestigator-frontend | |
| ``` | |
| ### 2. Install Dependencies | |
| ```bash | |
| npm install \ | |
| axios \ | |
| react-flow-renderer \ | |
| zustand \ | |
| react-icons \ | |
| react-toastify | |
| # Optional: for advanced visualizations | |
| npm install \ | |
| d3 \ | |
| cytoscape \ | |
| react-cytoscape | |
| ``` | |
| ### 3. Environment Setup | |
| ```bash | |
| # .env.local | |
| NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1 | |
| NEXT_PUBLIC_WS_URL=ws://localhost:8000 | |
| ``` | |
| --- | |
| ## π Key Pages & Components | |
| ### π Upload Papers (`/upload`) | |
| ```tsx | |
| // Features: | |
| - Drag & drop zone | |
| - Multiple file upload | |
| - PDF preview | |
| - Progress indicator | |
| - Metadata extraction preview | |
| // Key component: UploadZone.tsx | |
| ``` | |
| ### π Analysis Dashboard (`/analysis`) | |
| ```tsx | |
| // Features: | |
| - List of all analyses | |
| - Status indicators | |
| - Timeline view | |
| - Quick actions (view, export, delete) | |
| - Filtering & search | |
| // Key component: AnalysisList.tsx | |
| ``` | |
| ### π Analysis Details (`/analysis/[id]`) | |
| ```tsx | |
| // Features: | |
| - Tabs: Summary | Contradictions | Hypotheses | Gaps | Protocols | |
| - Reasoning trace visualization | |
| - Metrics display | |
| - Document references | |
| - Export options | |
| // Key components: | |
| // - ContradictionView.tsx (table with severity scores) | |
| // - ReasoningTracer.tsx (step-by-step breakdown) | |
| // - GraphVisualizer.tsx (document relationships) | |
| ``` | |
| ### π§ͺ Protocol Designer (`/protocols/[id]`) | |
| ```tsx | |
| // Features: | |
| - Protocol editor (rich text or form) | |
| - Variable specification | |
| - Risk assessment form | |
| - Cost/duration estimator | |
| - Version history | |
| - Export (PDF, DOCX, LaTeX) | |
| // Key component: ProtocolEditor.tsx | |
| ``` | |
| ### π Reasoning Trace Visualization | |
| ```tsx | |
| // Using React Flow: | |
| Nodes: Analysis steps | |
| Edges: Dependencies | |
| Styling: Color-coded by status (pending/active/complete) | |
| Interaction: Click to see details | |
| // Key component: GraphVisualizer.tsx with react-flow-renderer | |
| ``` | |
| --- | |
| ## π‘ API Integration | |
| ### API Client Setup | |
| ```typescript | |
| // lib/api/client.ts | |
| import axios from 'axios'; | |
| const apiClient = axios.create({ | |
| baseURL: process.env.NEXT_PUBLIC_API_URL, | |
| timeout: 30000, | |
| }); | |
| // Add token to requests | |
| apiClient.interceptors.request.use((config) => { | |
| const token = localStorage.getItem('token'); | |
| if (token) { | |
| config.headers.Authorization = `Bearer ${token}`; | |
| } | |
| return config; | |
| }); | |
| export default apiClient; | |
| ``` | |
| ### Main Endpoints to Integrate | |
| ```typescript | |
| // lib/api/endpoints.ts | |
| export const endpoints = { | |
| // Analysis | |
| analysis: { | |
| run: '/analysis/run', | |
| status: (id: string) => `/analysis/${id}/status`, | |
| results: (id: string) => `/analysis/${id}/results`, | |
| }, | |
| // Papers | |
| papers: { | |
| upload: '/papers/upload', | |
| list: (projectId: string) => `/papers/${projectId}`, | |
| }, | |
| // Protocols | |
| protocols: { | |
| generate: '/protocols/generate', | |
| list: '/protocols', | |
| detail: (id: string) => `/protocols/${id}`, | |
| export: (id: string, format: string) => `/protocols/${id}/export?format=${format}`, | |
| }, | |
| // Health | |
| health: '/health/ready', | |
| }; | |
| ``` | |
| ### Custom Hooks | |
| ```typescript | |
| // lib/hooks/useAnalysis.ts | |
| import { useState, useEffect } from 'react'; | |
| import apiClient from '@/lib/api/client'; | |
| export function useAnalysis(analysisId: string) { | |
| const [data, setData] = useState(null); | |
| const [loading, setLoading] = useState(true); | |
| const [error, setError] = useState(null); | |
| useEffect(() => { | |
| const fetchAnalysis = async () => { | |
| try { | |
| const response = await apiClient.get( | |
| `/analysis/${analysisId}/results` | |
| ); | |
| setData(response.data); | |
| } catch (err) { | |
| setError(err); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| fetchAnalysis(); | |
| }, [analysisId]); | |
| return { data, loading, error }; | |
| } | |
| ``` | |
| --- | |
| ## π¨ UI Components (Tailwind) | |
| ### Theme & Colors | |
| ```tsx | |
| // Suggested color scheme | |
| Primary: Blue-600 (reasoning) | |
| Secondary: Emerald-600 (validation) | |
| Danger: Red-600 (contradictions) | |
| Warning: Amber-600 (gaps) | |
| ``` | |
| ### Key Components to Build | |
| #### ContradictionCard | |
| ```tsx | |
| interface Contradiction { | |
| id: string; | |
| variable: string; | |
| confidence: number; | |
| statement_a: string; | |
| statement_b: string; | |
| severity: 'low' | 'medium' | 'high'; | |
| } | |
| <ContradictionCard | |
| contradiction={contradiction} | |
| onResolve={handleResolve} | |
| /> | |
| ``` | |
| #### HypothesisCard | |
| ```tsx | |
| <HypothesisCard | |
| hypothesis={hypothesis} | |
| stressTestResults={results} | |
| onSelect={handleSelect} | |
| /> | |
| ``` | |
| #### ProtocolTimeline | |
| ```tsx | |
| // Show: Hypothesis β Variables β Methodology β Risk Analysis β Export | |
| <ProtocolTimeline steps={protocolSteps} /> | |
| ``` | |
| --- | |
| ## π Graph Visualization (React Flow) | |
| ### Reasoning Trace Graph | |
| ```typescript | |
| // components/features/ReasoningTracer.tsx | |
| import { useCallback } from 'react'; | |
| import ReactFlow, { | |
| Node, | |
| Edge, | |
| useNodesState, | |
| useEdgesState | |
| } from 'reactflow'; | |
| const nodes: Node[] = [ | |
| { id: '1', data: { label: 'Extract Documents' }, position: { x: 0, y: 0 } }, | |
| { id: '2', data: { label: 'Detect Contradictions' }, position: { x: 250, y: 0 } }, | |
| // ... more nodes | |
| ]; | |
| const edges: Edge[] = [ | |
| { id: 'e1-2', source: '1', target: '2' }, | |
| // ... more edges | |
| ]; | |
| ``` | |
| --- | |
| ## π Authentication | |
| ### Token Management | |
| ```typescript | |
| // lib/api/auth.ts | |
| export const auth = { | |
| login: async (email: string, password: string) => { | |
| const response = await apiClient.post('/auth/login', { email, password }); | |
| localStorage.setItem('token', response.data.access_token); | |
| return response.data; | |
| }, | |
| logout: () => { | |
| localStorage.removeItem('token'); | |
| }, | |
| getToken: () => localStorage.getItem('token'), | |
| }; | |
| ``` | |
| --- | |
| ## π¦ Deployment Options | |
| ### Vercel (Recommended) | |
| ```bash | |
| # Connect GitHub repo to Vercel | |
| # Auto-deploys on push | |
| # Environment variables in Vercel dashboard | |
| NEXT_PUBLIC_API_URL=https://api.railway.app/api/v1 | |
| ``` | |
| ### Docker | |
| ```dockerfile | |
| FROM node:18-alpine | |
| WORKDIR /app | |
| COPY package*.json ./ | |
| RUN npm ci | |
| COPY . . | |
| RUN npm run build | |
| EXPOSE 3000 | |
| CMD ["npm", "start"] | |
| ``` | |
| --- | |
| ## π¨ Error Handling | |
| ```typescript | |
| // Global error boundary | |
| // components/layout/ErrorBoundary.tsx | |
| import { ReactNode } from 'react'; | |
| interface Props { | |
| children: ReactNode; | |
| } | |
| export default function ErrorBoundary({ children }: Props) { | |
| try { | |
| return <>{children}</>; | |
| } catch (error) { | |
| return ( | |
| <div className="bg-red-50 p-4 rounded"> | |
| <h2>Something went wrong</h2> | |
| <p>{error.message}</p> | |
| </div> | |
| ); | |
| } | |
| } | |
| ``` | |
| --- | |
| ## π± Responsive Design | |
| Use Tailwind breakpoints: | |
| ```tsx | |
| // Mobile first | |
| className="w-full md:w-1/2 lg:w-1/3" | |
| // Responsive grid | |
| className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" | |
| ``` | |
| --- | |
| ## π§ͺ Testing | |
| ```bash | |
| # Install testing dependencies | |
| npm install --save-dev @testing-library/react jest | |
| # Example test | |
| // __tests__/components/ContradictionCard.test.tsx | |
| import { render, screen } from '@testing-library/react'; | |
| import { ContradictionCard } from '@/components/features/ContradictionCard'; | |
| describe('ContradictionCard', () => { | |
| it('renders contradiction data', () => { | |
| const contradiction = { | |
| variable: 'sample_size', | |
| confidence: 0.95, | |
| }; | |
| render(<ContradictionCard contradiction={contradiction} />); | |
| expect(screen.getByText('sample_size')).toBeInTheDocument(); | |
| }); | |
| }); | |
| ``` | |
| --- | |
| ## π Quick Development Checklist | |
| - [ ] Setup Next.js project | |
| - [ ] Configure API client & endpoints | |
| - [ ] Create layout components (Header, Sidebar) | |
| - [ ] Implement upload page | |
| - [ ] Build analysis dashboard | |
| - [ ] Create analysis detail pages | |
| - [ ] Add protocol editor | |
| - [ ] Implement reasoning trace visualization | |
| - [ ] Setup authentication flow | |
| - [ ] Add error handling & loading states | |
| - [ ] Global styling with Tailwind | |
| - [ ] Responsive design testing | |
| - [ ] Performance optimization | |
| - [ ] Deploy to Vercel | |
| --- | |
| ## π― UX/Design Tips for Jury | |
| **Scientific credibility:** | |
| - Show data sources and references | |
| - Display confidence scores | |
| - Allow result verification | |
| - Show reasoning steps | |
| **Visual hierarchy:** | |
| - Emphasize contradictions clearly | |
| - Highlight key hypotheses | |
| - Color-code severity/confidence | |
| - Use data visualization effectively | |
| **Performance:** | |
| - Quick upload/processing feedback | |
| - Real-time progress indicators | |
| - Smooth transitions | |
| - Responsive to all devices | |
| --- | |
| ## π Resources | |
| - [Next.js Docs](https://nextjs.org/docs) | |
| - [React Flow](https://reactflow.dev/) | |
| - [Tailwind CSS](https://tailwindcss.com/) | |
| - [TypeScript](https://www.typescriptlang.org/) | |
| - [Axios](https://axios-http.com/) | |
| --- | |
| Happy building! π | |