diff --git a/Dockerfile.app b/Dockerfile.app
index c78e349a..c021d914 100644
--- a/Dockerfile.app
+++ b/Dockerfile.app
@@ -40,10 +40,10 @@ COPY src/ ./src/
RUN echo '#!/bin/bash\n\
set -e\n\
echo "Starting Python backend..."\n\
-uv run python src/app.py &\n\
+uv run python src/main.py &\n\
BACKEND_PID=$!\n\
echo "Waiting for backend to be ready..."\n\
-until curl -f http://localhost:8000/search -X POST -H "Content-Type: application/json" -d "{\"query\":\"test\"}" > /dev/null 2>&1; do\n\
+until curl -f http://localhost:8000/auth/me > /dev/null 2>&1; do\n\
echo "Backend not ready yet, waiting..."\n\
sleep 2\n\
done\n\
diff --git a/Dockerfile.backend b/Dockerfile.backend
new file mode 100644
index 00000000..a009496e
--- /dev/null
+++ b/Dockerfile.backend
@@ -0,0 +1,29 @@
+FROM python:3.13-slim
+
+# Install curl for uv installation
+RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
+
+# Install uv
+RUN curl -LsSf https://astral.sh/uv/install.sh | sh
+ENV PATH="/root/.local/bin:$PATH"
+
+# Set working directory
+WORKDIR /app
+
+# Copy Python dependencies
+COPY pyproject.toml uv.lock ./
+RUN uv sync
+
+# Copy sample document and warmup script for docling
+COPY documents/2506.08231v1.pdf ./
+COPY warm_up_docling.py ./
+RUN uv run python warm_up_docling.py && rm warm_up_docling.py 2506.08231v1.pdf
+
+# Copy Python source
+COPY src/ ./src/
+
+# Expose backend port
+EXPOSE 8000
+
+# Start backend in foreground
+CMD ["uv", "run", "python", "src/main.py"]
\ No newline at end of file
diff --git a/Dockerfile.frontend b/Dockerfile.frontend
new file mode 100644
index 00000000..a60e3d34
--- /dev/null
+++ b/Dockerfile.frontend
@@ -0,0 +1,20 @@
+FROM node:18-slim
+
+# Set working directory
+WORKDIR /app
+
+# Copy frontend dependencies
+COPY frontend/package*.json ./
+RUN npm install
+
+# Copy frontend source
+COPY frontend/ ./
+
+# Build frontend
+RUN npm run build
+
+# Expose frontend port
+EXPOSE 3000
+
+# Start frontend in foreground
+CMD ["npm", "start"]
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index 04168f7b..c02489c9 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -23,12 +23,11 @@ services:
ports:
- "5601:5601"
- gendb:
- image: phact/gendb:latest
- #build:
- #context: .
- #dockerfile: Dockerfile.app
- container_name: gendb-app
+ gendb-backend:
+ build:
+ context: .
+ dockerfile: Dockerfile.backend
+ container_name: gendb-backend
depends_on:
- opensearch
- langflow
@@ -43,17 +42,30 @@ services:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- NVIDIA_DRIVER_CAPABILITIES=compute,utility
- NVIDIA_VISIBLE_DEVICES=all
- ports:
- - "3000:3000"
+ - GOOGLE_OAUTH_CLIENT_ID=${GOOGLE_OAUTH_CLIENT_ID}
+ - GOOGLE_OAUTH_CLIENT_SECRET=${GOOGLE_OAUTH_CLIENT_SECRET}
volumes:
- ./src:/app/src
- - ./frontend/src:/app/frontend/src
- ./pyproject.toml:/app/pyproject.toml
- ./uv.lock:/app/uv.lock
- ./documents:/app/documents
gpus: all
platform: linux/amd64
+ gendb-frontend:
+ build:
+ context: .
+ dockerfile: Dockerfile.frontend
+ container_name: gendb-frontend
+ depends_on:
+ - gendb-backend
+ environment:
+ - GENDB_BACKEND_HOST=gendb-backend
+ ports:
+ - "3000:3000"
+ volumes:
+ - ./frontend/src:/app/src
+
langflow:
volumes:
- ./flows:/app/flows
diff --git a/frontend/next.config.ts b/frontend/next.config.ts
index ab7b4aa6..14dc986f 100644
--- a/frontend/next.config.ts
+++ b/frontend/next.config.ts
@@ -1,14 +1,6 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
- async rewrites() {
- return [
- {
- source: '/api/:path*',
- destination: 'http://localhost:8000/:path*',
- },
- ];
- },
// Increase timeout for API routes
experimental: {
proxyTimeout: 300000, // 5 minutes
diff --git a/frontend/src/app/api/[...path]/route.ts b/frontend/src/app/api/[...path]/route.ts
new file mode 100644
index 00000000..a5dcc779
--- /dev/null
+++ b/frontend/src/app/api/[...path]/route.ts
@@ -0,0 +1,92 @@
+import { NextRequest, NextResponse } from 'next/server';
+
+export async function GET(
+ request: NextRequest,
+ { params }: { params: Promise<{ path: string[] }> }
+) {
+ return proxyRequest(request, await params);
+}
+
+export async function POST(
+ request: NextRequest,
+ { params }: { params: Promise<{ path: string[] }> }
+) {
+ return proxyRequest(request, await params);
+}
+
+export async function PUT(
+ request: NextRequest,
+ { params }: { params: Promise<{ path: string[] }> }
+) {
+ return proxyRequest(request, await params);
+}
+
+export async function DELETE(
+ request: NextRequest,
+ { params }: { params: Promise<{ path: string[] }> }
+) {
+ return proxyRequest(request, await params);
+}
+
+export async function PATCH(
+ request: NextRequest,
+ { params }: { params: Promise<{ path: string[] }> }
+) {
+ return proxyRequest(request, await params);
+}
+
+async function proxyRequest(
+ request: NextRequest,
+ params: { path: string[] }
+) {
+ const backendHost = process.env.GENDB_BACKEND_HOST || 'localhost';
+ const path = params.path.join('/');
+ const searchParams = request.nextUrl.searchParams.toString();
+ const backendUrl = `http://${backendHost}:8000/${path}${searchParams ? `?${searchParams}` : ''}`;
+
+ try {
+ const body = request.method !== 'GET' && request.method !== 'HEAD'
+ ? await request.text()
+ : undefined;
+
+ const headers = new Headers();
+
+ // Copy relevant headers from the original request
+ for (const [key, value] of request.headers.entries()) {
+ if (!key.toLowerCase().startsWith('host') &&
+ !key.toLowerCase().startsWith('x-forwarded') &&
+ !key.toLowerCase().startsWith('x-real-ip')) {
+ headers.set(key, value);
+ }
+ }
+
+ const response = await fetch(backendUrl, {
+ method: request.method,
+ headers,
+ body,
+ });
+
+ const responseBody = await response.text();
+ const responseHeaders = new Headers();
+
+ // Copy response headers
+ for (const [key, value] of response.headers.entries()) {
+ if (!key.toLowerCase().startsWith('transfer-encoding') &&
+ !key.toLowerCase().startsWith('connection')) {
+ responseHeaders.set(key, value);
+ }
+ }
+
+ return new NextResponse(responseBody, {
+ status: response.status,
+ statusText: response.statusText,
+ headers: responseHeaders,
+ });
+ } catch (error) {
+ console.error('Proxy error:', error);
+ return NextResponse.json(
+ { error: 'Failed to proxy request' },
+ { status: 500 }
+ );
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/app/auth/callback/page.tsx b/frontend/src/app/auth/callback/page.tsx
index df40521a..d93c99ed 100644
--- a/frontend/src/app/auth/callback/page.tsx
+++ b/frontend/src/app/auth/callback/page.tsx
@@ -1,13 +1,13 @@
"use client"
-import { useEffect, useState, useRef } from "react"
+import { useEffect, useState, useRef, Suspense } from "react"
import { useRouter, useSearchParams } from "next/navigation"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Loader2, CheckCircle, XCircle, ArrowLeft } from "lucide-react"
import { useAuth } from "@/contexts/auth-context"
-export default function AuthCallbackPage() {
+function AuthCallbackContent() {
const router = useRouter()
const searchParams = useSearchParams()
const { refreshAuth } = useAuth()
@@ -211,4 +211,26 @@ export default function AuthCallbackPage() {
)
+}
+
+export default function AuthCallbackPage() {
+ return (
+
+
+
+
+
+ Loading...
+
+
+ Please wait while we process your request...
+
+
+
+
+ }>
+
+
+ )
}
\ No newline at end of file
diff --git a/frontend/src/app/connectors/page.tsx b/frontend/src/app/connectors/page.tsx
index 121c9707..a7600f94 100644
--- a/frontend/src/app/connectors/page.tsx
+++ b/frontend/src/app/connectors/page.tsx
@@ -1,6 +1,6 @@
"use client"
-import { useState, useEffect } from "react"
+import { useState, useEffect, Suspense } from "react"
import { useSearchParams } from "next/navigation"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
@@ -467,7 +467,9 @@ function ConnectorsPage() {
export default function ProtectedConnectorsPage() {
return (
-
+ Loading connectors...}>
+
+
)
}
\ No newline at end of file
diff --git a/frontend/src/app/login/page.tsx b/frontend/src/app/login/page.tsx
index fca2c5b0..ea095f3e 100644
--- a/frontend/src/app/login/page.tsx
+++ b/frontend/src/app/login/page.tsx
@@ -1,13 +1,13 @@
"use client"
-import { useEffect } from "react"
+import { useEffect, Suspense } from "react"
import { useRouter, useSearchParams } from "next/navigation"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { useAuth } from "@/contexts/auth-context"
import { Lock, LogIn, Loader2 } from "lucide-react"
-export default function LoginPage() {
+function LoginPageContent() {
const { isLoading, isAuthenticated, login } = useAuth()
const router = useRouter()
const searchParams = useSearchParams()
@@ -62,4 +62,19 @@ export default function LoginPage() {
)
+}
+
+export default function LoginPage() {
+ return (
+
+
+
+ }>
+
+
+ )
}
\ No newline at end of file