feat: add landing page with API docs at root URL

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-02-08 13:14:13 +00:00
parent 1784bb35ff
commit 53c1ed5c4c
1 changed files with 27 additions and 0 deletions

View File

@ -2,6 +2,7 @@ from contextlib import asynccontextmanager
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import HTMLResponse
from app.api.routes import jobs, clips, renders from app.api.routes import jobs, clips, renders
@ -31,6 +32,32 @@ app.include_router(clips.router, prefix="/api")
app.include_router(renders.router, prefix="/api") app.include_router(renders.router, prefix="/api")
@app.get("/", response_class=HTMLResponse)
async def root():
return """<!DOCTYPE html><html><head><title>ClipForge</title>
<style>*{margin:0;padding:0;box-sizing:border-box}body{font-family:system-ui,-apple-system,sans-serif;background:#0a0a0a;color:#e0e0e0;min-height:100vh;display:flex;justify-content:center;align-items:center}
main{max-width:640px;padding:2rem;text-align:center}h1{font-size:2.5rem;margin-bottom:.5rem}
.sub{color:#888;margin-bottom:2rem}.card{background:#141414;border:1px solid #2a2a2a;border-radius:12px;padding:1.5rem;text-align:left;margin-bottom:1rem}
.card h3{color:#fff;margin-bottom:.75rem}code{background:#1a1a1a;padding:2px 6px;border-radius:4px;font-size:.85rem;color:#4ade80}
.endpoint{margin:.5rem 0;line-height:1.6}.method{color:#f59e0b;font-weight:700;margin-right:.5rem}
.status{display:inline-block;width:8px;height:8px;border-radius:50%;background:#4ade80;margin-right:6px}
</style></head><body><main>
<h1>ClipForge</h1><p class="sub">Self-hosted AI video clipper</p>
<div class="card"><h3><span class="status"></span>API Endpoints</h3>
<div class="endpoint"><span class="method">POST</span><code>/api/jobs</code> Create job (YouTube URL)</div>
<div class="endpoint"><span class="method">POST</span><code>/api/jobs/upload</code> Upload video file</div>
<div class="endpoint"><span class="method">GET</span><code>/api/jobs/{id}</code> Job status</div>
<div class="endpoint"><span class="method">GET</span><code>/api/jobs/{id}/clips</code> Get clips</div>
<div class="endpoint"><span class="method">GET</span><code>/api/jobs/{id}/progress</code> SSE progress stream</div>
<div class="endpoint"><span class="method">POST</span><code>/api/clips/{id}/render</code> Render clip</div>
<div class="endpoint"><span class="method">GET</span><code>/api/renders/{id}/download</code> Download render</div>
</div>
<div class="card"><h3>Interactive Docs</h3>
<p style="line-height:1.6"><a href="/docs" style="color:#60a5fa">/docs</a> &mdash; Swagger UI<br>
<a href="/redoc" style="color:#60a5fa">/redoc</a> &mdash; ReDoc</p>
</div></main></body></html>"""
@app.get("/health") @app.get("/health")
async def health(): async def health():
return {"status": "ok", "service": "clipforge"} return {"status": "ok", "service": "clipforge"}