"""Main FastAPI application with blog module.""" from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import RedirectResponse from pathlib import Path from starlette.staticfiles import StaticFiles # Load .env file if python-dotenv is available try: from dotenv import load_dotenv env_path = Path(__file__).parent / ".env" if env_path.exists(): load_dotenv(env_path) except ImportError: pass from blog import blog_router, brief_router from blog.admin_router import admin_router, setup_admin_static from content import router as content_router from family import family_router from webhook_public import webhook_router from auth.router import auth_router from shared.session_auth import SessionAuthMiddleware from dashboard.router import router as dashboard_router app = FastAPI( title="HoffDesk API", description="HoffDesk Blog and Dashboard API", version="1.0.0" ) # Session auth middleware (must be before CORS for proper handling) app.add_middleware(SessionAuthMiddleware) # CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], # Configure appropriately for production allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Mount blog static files (CSS, images) BLOG_STATIC_DIR = Path("/home/hoffmann_admin/hoffdesk/blog/static") app.mount("/blog/static", StaticFiles(directory=str(BLOG_STATIC_DIR)), name="blog_static") # Mount dashboard static files at /static/ for family.hoffdesk.com DASHBOARD_STATIC_DIR = Path("/home/hoffmann_admin/.openclaw/shared/project-docs/dashboard/static") app.mount("/static", StaticFiles(directory=str(DASHBOARD_STATIC_DIR)), name="dashboard_static") # Include dashboard router app.include_router( dashboard_router, tags=["dashboard"] ) # Include auth router (must be before protected routes) app.include_router( auth_router, prefix="/auth", tags=["auth"] ) # Include blog router app.include_router( blog_router, prefix="/api/blog", tags=["blog"] ) # Include admin router app.include_router( admin_router, prefix="/admin/blog", tags=["blog-admin"] ) # Include content generation router app.include_router( content_router, prefix="/admin", tags=["content-generation"] ) # Include family automation router (private household) app.include_router( family_router, prefix="/admin", tags=["family-automation"] ) # Include public webhook router (no auth, for Cloudflare Worker) app.include_router( webhook_router, tags=["webhook"] ) # Include content briefs router app.include_router( brief_router, prefix="/api/v1/content/briefs", tags=["content-briefs"] ) # Setup admin static files setup_admin_static(app) @app.get("/") def root(): """Root endpoint — redirect to blog.""" return RedirectResponse(url="/api/blog/", status_code=302) @app.get("/health") def health(): """Health check endpoint.""" return {"status": "healthy"} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)