-
Notifications
You must be signed in to change notification settings - Fork 0
Build Production-Ready Next.js Frontend for NeuraX RAG System #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
cto-new
wants to merge
1
commit into
master
Choose a base branch
from
cto-task-build-a-production-ready-next-js-frontend-for-neurax-rag-sys-e01
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Backend API Server Requirements | ||
| fastapi==0.104.1 | ||
| uvicorn[standard]==0.24.0 | ||
| python-multipart==0.0.6 | ||
| pydantic==2.5.0 | ||
| python-jose[cryptography]==3.3.0 | ||
| passlib[bcrypt]==1.7.4 | ||
| aiofiles==23.2.0 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # Environment variables for NeuraX Frontend | ||
| # Copy this file to .env.local and configure as needed | ||
|
|
||
| # API Configuration | ||
| NEXT_PUBLIC_API_URL=http://localhost:8000 | ||
| NEXT_PUBLIC_WS_URL=ws://localhost:8000 | ||
| NEXT_PUBLIC_LM_STUDIO_URL=http://localhost:1234 | ||
|
|
||
| # File Upload Settings | ||
| NEXT_PUBLIC_MAX_FILE_SIZE=104857600 | ||
| NEXT_PUBLIC_ALLOWED_FILE_TYPES=.pdf,.docx,.doc,.txt,.jpg,.png,.mp3,.wav,.m4a,.flac,.ogg,.bmp,.tiff,.webp | ||
|
|
||
| # Feature Flags | ||
| NEXT_PUBLIC_ENABLE_ANALYTICS=true | ||
| NEXT_PUBLIC_ENABLE_DARK_MODE=true | ||
| NEXT_PUBLIC_ENABLE_VOICE_INPUT=true | ||
|
|
||
| # Query Settings | ||
| NEXT_PUBLIC_DEFAULT_SIMILARITY_THRESHOLD=0.5 | ||
| NEXT_PUBLIC_MAX_QUERY_HISTORY=50 | ||
|
|
||
| # Development Settings | ||
| NEXT_PUBLIC_DEBUG_MODE=false | ||
| NEXT_PUBLIC_LOG_LEVEL=info | ||
|
|
||
| # Optional: Custom model configurations | ||
| # NEXT_PUBLIC_CUSTOM_MODELS_PATH=/path/to/models | ||
| # NEXT_PUBLIC_ENABLE_EXPERIMENTAL_FEATURES=false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # NeuraX Frontend Environment Variables | ||
| NEXT_PUBLIC_API_URL=http://localhost:8000 | ||
| NEXT_PUBLIC_WS_URL=ws://localhost:8000 | ||
| NEXT_PUBLIC_LM_STUDIO_URL=http://localhost:1234 | ||
| NEXT_PUBLIC_MAX_FILE_SIZE=104857600 | ||
| NEXT_PUBLIC_ALLOWED_FILE_TYPES=.pdf,.docx,.doc,.txt,.jpg,.png,.mp3,.wav,.m4a,.flac,.ogg,.bmp,.tiff,.webp | ||
| NEXT_PUBLIC_ENABLE_ANALYTICS=true | ||
| NEXT_PUBLIC_ENABLE_DARK_MODE=true | ||
| NEXT_PUBLIC_DEFAULT_SIMILARITY_THRESHOLD=0.5 | ||
| NEXT_PUBLIC_MAX_QUERY_HISTORY=50 | ||
| NEXT_PUBLIC_ENABLE_VOICE_INPUT=true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # Use the official Node.js 18 image | ||
| FROM node:18-alpine AS base | ||
|
|
||
| # Install dependencies only when needed | ||
| FROM base AS deps | ||
| # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. | ||
| RUN apk add --no-cache libc6-compat | ||
| WORKDIR /app | ||
|
|
||
| # Install dependencies based on the preferred package manager | ||
| COPY package.json package-lock.json* ./ | ||
| RUN npm ci --only=production && npm cache clean --force | ||
|
|
||
| # Rebuild the source code only when needed | ||
| FROM base AS builder | ||
| WORKDIR /app | ||
| COPY --from=deps /app/node_modules ./node_modules | ||
| COPY . . | ||
|
|
||
| # Next.js collects completely anonymous telemetry data about general usage. | ||
| # Learn more here: https://nextjs.org/telemetry | ||
| # Uncomment the following line in case you want to disable telemetry during the build. | ||
| ENV NEXT_TELEMETRY_DISABLED 1 | ||
|
|
||
| RUN npm run build | ||
|
|
||
| # If using npm comment out above and use below instead | ||
| # RUN npm run build | ||
|
|
||
| # Production image, copy all the files and run next | ||
| FROM base AS runner | ||
| WORKDIR /app | ||
|
|
||
| ENV NODE_ENV production | ||
| # Uncomment the following line in case you want to disable telemetry during runtime. | ||
| ENV NEXT_TELEMETRY_DISABLED 1 | ||
|
|
||
| RUN addgroup --system --gid 1001 nodejs | ||
| RUN adduser --system --uid 1001 nextjs | ||
|
|
||
| COPY --from=builder /app/public ./public | ||
|
|
||
| # Set the correct permission for prerender cache | ||
| RUN mkdir .next | ||
| RUN chown nextjs:nodejs .next | ||
|
|
||
| # Automatically leverage output traces to reduce image size | ||
| # https://nextjs.org/docs/advanced-features/output-file-tracing | ||
| COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ | ||
| COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static | ||
|
|
||
| USER nextjs | ||
|
|
||
| EXPOSE 3000 | ||
|
|
||
| ENV PORT 3000 | ||
| # set hostname to localhost | ||
| ENV HOSTNAME "0.0.0.0" | ||
|
|
||
| # server.js is created by next build from the standalone output | ||
| # https://nextjs.org/docs/pages/api-reference/next-config-js/output | ||
| CMD ["node", "server.js"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| import type { Metadata } from 'next' | ||
| import { Inter } from 'next/font/google' | ||
| import './globals.css' | ||
| import { Toaster } from 'react-hot-toast' | ||
|
|
||
| const inter = Inter({ subsets: ['latin'] }) | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: 'NeuraX - Multimodal RAG System', | ||
| description: 'Secure, offline multimodal retrieval-augmented generation system with document intelligence and analytics.', | ||
| keywords: 'RAG, multimodal, document intelligence, AI, security, offline', | ||
| authors: [{ name: 'NeuraX Team' }], | ||
| viewport: 'width=device-width, initial-scale=1', | ||
| } | ||
|
|
||
| export default function RootLayout({ | ||
| children, | ||
| }: { | ||
| children: React.ReactNode | ||
| }) { | ||
| return ( | ||
| <html lang="en" suppressHydrationWarning> | ||
| <body className={inter.className}> | ||
| <div className="relative flex min-h-screen flex-col"> | ||
| {children} | ||
| </div> | ||
| <Toaster | ||
| position="top-right" | ||
| toastOptions={{ | ||
| duration: 4000, | ||
| style: { | ||
| background: 'hsl(var(--background))', | ||
| color: 'hsl(var(--foreground))', | ||
| border: '1px solid hsl(var(--border))', | ||
| }, | ||
| success: { | ||
| className: 'toast-success', | ||
| }, | ||
| error: { | ||
| className: 'toast-error', | ||
| }, | ||
| loading: { | ||
| className: 'toast-info', | ||
| }, | ||
| }} | ||
| /> | ||
| </body> | ||
| </html> | ||
| ) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| 'use client' | ||
|
|
||
| import { useState, useCallback } from 'react' | ||
| import { Header } from '@/components/common/Header' | ||
| import { FileUploader } from '@/components/upload/FileUploader' | ||
| import { QueryInterface } from '@/components/query/QueryInterface' | ||
| import { ResultsDisplay } from '@/components/results/ResultsDisplay' | ||
| import { AnalyticsDashboard } from '@/components/analytics/AnalyticsDashboard' | ||
| import { QueryHistory } from '@/components/query/QueryHistory' | ||
| import { Settings } from '@/components/common/Settings' | ||
| import { Card, CardContent } from '@/components/ui/card' | ||
| import { Button } from '@/components/ui/button' | ||
| import { FileText, Search, BarChart3, History, Settings as SettingsIcon, Upload } from 'lucide-react' | ||
| import type { Query, SearchResult, FileUpload } from '@/types' | ||
|
|
||
| export default function HomePage() { | ||
| const [activeTab, setActiveTab] = useState<'query' | 'upload' | 'analytics' | 'history' | 'settings'>('query') | ||
| const [currentQuery, setCurrentQuery] = useState<Query | null>(null) | ||
| const [searchResults, setSearchResults] = useState<SearchResult[]>([]) | ||
| const [uploadedFiles, setUploadedFiles] = useState<FileUpload[]>([]) | ||
|
|
||
| const handleSearch = useCallback((query: Query) => { | ||
| setCurrentQuery(query) | ||
| // Search results will be set by the QueryInterface component | ||
| }, []) | ||
|
|
||
| const handleSearchResults = useCallback((results: SearchResult[]) => { | ||
| setSearchResults(results) | ||
| }, []) | ||
|
|
||
| const handleFileUpload = useCallback((files: FileUpload[]) => { | ||
| setUploadedFiles(prev => [...prev, ...files]) | ||
| }, []) | ||
|
|
||
| const renderActiveTab = () => { | ||
| switch (activeTab) { | ||
| case 'upload': | ||
| return ( | ||
| <FileUploader | ||
| onFileUpload={handleFileUpload} | ||
| uploadedFiles={uploadedFiles} | ||
| /> | ||
| ) | ||
| case 'analytics': | ||
| return <AnalyticsDashboard /> | ||
| case 'history': | ||
| return <QueryHistory /> | ||
| case 'settings': | ||
| return <Settings /> | ||
| case 'query': | ||
| default: | ||
| return ( | ||
| <div className="space-y-6"> | ||
| <QueryInterface | ||
| onSearch={handleSearch} | ||
| onResults={handleSearchResults} | ||
| uploadedFiles={uploadedFiles} | ||
| /> | ||
| {searchResults.length > 0 && ( | ||
| <ResultsDisplay | ||
| query={currentQuery} | ||
| results={searchResults} | ||
| /> | ||
| )} | ||
| </div> | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| return ( | ||
| <div className="min-h-screen bg-background"> | ||
| <Header | ||
| onSearch={() => setActiveTab('query')} | ||
| onUpload={() => setActiveTab('upload')} | ||
| onAnalytics={() => setActiveTab('analytics')} | ||
| onHistory={() => setActiveTab('history')} | ||
| onSettings={() => setActiveTab('settings')} | ||
| /> | ||
|
|
||
| <main className="container mx-auto px-4 py-6"> | ||
| {/* Tab Navigation */} | ||
| <div className="mb-6"> | ||
| <div className="flex space-x-1 rounded-lg bg-muted p-1"> | ||
| <Button | ||
| variant={activeTab === 'query' ? 'default' : 'ghost'} | ||
| size="sm" | ||
| onClick={() => setActiveTab('query')} | ||
| className="gap-2" | ||
| > | ||
| <Search className="h-4 w-4" /> | ||
| Query & Search | ||
| </Button> | ||
| <Button | ||
| variant={activeTab === 'upload' ? 'default' : 'ghost'} | ||
| size="sm" | ||
| onClick={() => setActiveTab('upload')} | ||
| className="gap-2" | ||
| > | ||
| <Upload className="h-4 w-4" /> | ||
| File Upload | ||
| </Button> | ||
| <Button | ||
| variant={activeTab === 'analytics' ? 'default' : 'ghost'} | ||
| size="sm" | ||
| onClick={() => setActiveTab('analytics')} | ||
| className="gap-2" | ||
| > | ||
| <BarChart3 className="h-4 w-4" /> | ||
| Analytics | ||
| </Button> | ||
| <Button | ||
| variant={activeTab === 'history' ? 'default' : 'ghost'} | ||
| size="sm" | ||
| onClick={() => setActiveTab('history')} | ||
| className="gap-2" | ||
| > | ||
| <History className="h-4 w-4" /> | ||
| History | ||
| </Button> | ||
| <Button | ||
| variant={activeTab === 'settings' ? 'default' : 'ghost'} | ||
| size="sm" | ||
| onClick={() => setActiveTab('settings')} | ||
| className="gap-2" | ||
| > | ||
| <SettingsIcon className="h-4 w-4" /> | ||
| Settings | ||
| </Button> | ||
| </div> | ||
| </div> | ||
|
|
||
| {/* Tab Content */} | ||
| <div className="animate-fade-in"> | ||
| {renderActiveTab()} | ||
| </div> | ||
|
|
||
| {/* Quick Stats Footer */} | ||
| {activeTab === 'query' && ( | ||
| <Card className="mt-8"> | ||
| <CardContent className="pt-6"> | ||
| <div className="flex items-center justify-between text-sm text-muted-foreground"> | ||
| <div className="flex items-center space-x-4"> | ||
| <div className="flex items-center space-x-1"> | ||
| <div className="h-2 w-2 bg-green-500 rounded-full" /> | ||
| <span>{uploadedFiles.length} files uploaded</span> | ||
| </div> | ||
| <div className="flex items-center space-x-1"> | ||
| <div className="h-2 w-2 bg-blue-500 rounded-full" /> | ||
| <span>{searchResults.length} results found</span> | ||
| </div> | ||
| </div> | ||
| <div> | ||
| System Status: Online | ||
| </div> | ||
| </div> | ||
| </CardContent> | ||
| </Card> | ||
| )} | ||
| </main> | ||
| </div> | ||
| ) | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π§© Analysis chain
π Script executed:
Repository: thrishank007/NeuraX
Length of output: 1195
π Web query:
fastapi latest version 2024 2025 security updatesπ‘ Result:
Latest FastAPI version (as of Jan 30, 2026)
Notable 2024β2025 security-relevant updates (FastAPI + common transitive issues)
python-multipartwhen parsing form-dataContent-Type)python-multipart >= 0.0.7) (data.safetycli.com)Practical guidance
python-multipartReDoS fix). (data.safetycli.com)Citations:
π Web query:
uvicorn latest version 2024 2025 security advisoriesπ‘ Result:
Latest Uvicorn (Python / PyPI)
Security advisories relevant to 2024β2025
Uvicorn (Python) CVEs/advisories
There donβt appear to be newly issued 2024β2025 CVEs for the PyPI
uvicornpackage itself in the major public advisory feeds surfaced here; the commonly referenced Uvicorn issues are older, but their advisory records were updated in Nov 2024:βUvicornβ mentioned in 2024β2025 CVEs, but not a Uvicorn bug
Name-collision warning: malicious npm package named
uvicorn(not Python Uvicorn)uvicornon npm (JavaScript ecosystem). This is separate from Pythonβsuvicornon PyPI. (osv.dev)Practical takeaway
uvicornpackage (malware advisory above). (osv.dev)Citations:
π Web query:
pydantic 2.5.0 latest version 2024 2025 securityπ‘ Result:
Security (2024β2025)
Practical recommendation
Sources:
[1] PyPI pydantic (latest version/date)
[2] GitHub Advisory Database entry for CVE-2024-3772 (affected/patched versions)
[3] Pydantic changelog entry for v2.5.0 (release date)
[4] Ubuntu CVE entry for CVE-2024-3772 (description/affected versions)
π Web query:
python-jose passlib aiofiles latest versions 2024 2025π‘ Result:
Latest as of Jan 30, 2026 (from PyPI):
python-josepython-joserelease. [1]passlibpasslibitself. [2]libpassaiofiles2024β2025 highlights:
python-jose: latest in that window is 3.5.0 (May 28, 2025). [1]passlib: no releases in 2024/2025 (latest remains 1.7.4 from 2020). [2]aiofiles: 24.1.0 (Jun 24, 2024) and 25.1.0 (Oct 9, 2025). [4]libpass(e.g., 1.8.x in 2024, 1.9.x in 2025). [3]Sources: [1]
python-joseon PyPI, [2]passlibon PyPI, [3]libpasson PyPI, [4]aiofileson PyPI.Address CVE-2024-24762: upgrade FastAPI and python-multipart to patch ReDoS vulnerability in form-data parsing.
The current pins (
fastapi==0.104.1withpython-multipart==0.0.6) are vulnerable to CVE-2024-24762, a ReDoS attack exploitable via craftedContent-Typeheaders in multipart form submissions. Minimum safe versions arefastapi>=0.109.1andpython-multipart>=0.0.7. Consider upgrading to current releases:fastapito0.128.0(Dec 2025)uvicornto0.40.0(Dec 2025)pydanticto2.12.5(latest v2 stable, Nov 2025)python-joseto3.5.0(May 2025)aiofilesto25.1.0(Oct 2025)passlibremains at1.7.4(project unmaintained since 2020; considerlibpassfork if active maintenance is needed)π€ Prompt for AI Agents