Rewrite from Go + vanilla JS to Python (FastAPI) + React (TypeScript)

- Backend: Python 3.12 with FastAPI, SQLAlchemy, boto3
- Frontend: React 18 with TypeScript, Vite build tooling
- Updated Dockerfile for multi-stage Node + Python build
- Updated CI pipeline for Python backend
- Removed old Go code (cmd/, internal/, go.mod, go.sum)
- Updated README with new tech stack documentation
This commit is contained in:
Mondo Diaz
2025-12-05 17:16:43 -06:00
parent 343f7bfc59
commit 2261bfc830
45 changed files with 2104 additions and 3359 deletions

54
backend/app/main.py Normal file
View File

@@ -0,0 +1,54 @@
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from contextlib import asynccontextmanager
import os
from .config import get_settings
from .database import init_db
from .routes import router
settings = get_settings()
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup: initialize database
init_db()
yield
# Shutdown: cleanup if needed
app = FastAPI(
title="Orchard",
description="Content-Addressable Storage System",
version="1.0.0",
lifespan=lifespan,
)
# Include API routes
app.include_router(router)
# Serve static files (React build) if the directory exists
static_dir = os.path.join(os.path.dirname(__file__), "..", "..", "frontend", "dist")
if os.path.exists(static_dir):
app.mount("/assets", StaticFiles(directory=os.path.join(static_dir, "assets")), name="assets")
@app.get("/")
async def serve_spa():
return FileResponse(os.path.join(static_dir, "index.html"))
# Catch-all for SPA routing (must be last)
@app.get("/{full_path:path}")
async def serve_spa_routes(full_path: str):
# Don't catch API routes
if full_path.startswith("api/") or full_path.startswith("health") or full_path.startswith("grove/"):
from fastapi import HTTPException
raise HTTPException(status_code=404, detail="Not found")
index_path = os.path.join(static_dir, "index.html")
if os.path.exists(index_path):
return FileResponse(index_path)
from fastapi import HTTPException
raise HTTPException(status_code=404, detail="Not found")