feat(gui): add FastAPI + Jinja2 + HTMX scaffold

- FastAPI app with Jinja2 templates and Pico CSS + HTMX from CDN
- Routes: GET / (placeholder page), GET /health (JSON healthcheck)
- systemd unit (no Install section - manual start only)
- TestClient tests for both endpoints

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Matt Johnson 2026-05-17 04:32:39 +00:00
commit 614312db36
9 changed files with 437 additions and 0 deletions

View file

@ -0,0 +1,46 @@
"""Central GUI — FastAPI + Jinja2 + HTMX."""
from pathlib import Path
import uvicorn
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from central.gui.routes import router
# Template and static directories
GUI_DIR = Path(__file__).parent
TEMPLATES_DIR = GUI_DIR / "templates"
STATIC_DIR = GUI_DIR / "static"
# Jinja2 templates instance (shared with routes)
templates = Jinja2Templates(directory=str(TEMPLATES_DIR))
def create_app() -> FastAPI:
"""Create and configure the FastAPI application."""
app = FastAPI(
title="Central",
description="Central Data Hub GUI",
docs_url=None, # Disable Swagger UI for now
redoc_url=None, # Disable ReDoc for now
)
# Mount static files if directory exists and has content
if STATIC_DIR.exists():
app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
# Include routes
app.include_router(router)
return app
# Application instance
app = create_app()
def main() -> None:
"""Entry point for central-gui console script."""
uvicorn.run(app, host="127.0.0.1", port=8000)

23
src/central/gui/routes.py Normal file
View file

@ -0,0 +1,23 @@
"""Route handlers for Central GUI."""
from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse
router = APIRouter()
@router.get("/health")
async def health() -> dict:
"""Health check endpoint."""
return {"status": "ok"}
@router.get("/", response_class=HTMLResponse)
async def index(request: Request) -> HTMLResponse:
"""Render the index page."""
from central.gui import templates
return templates.TemplateResponse(
request=request,
name="index.html",
)

View file

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Central{% endblock %}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
{% block head %}{% endblock %}
</head>
<body>
<main class="container">
{% block content %}{% endblock %}
</main>
</body>
</html>

View file

@ -0,0 +1,12 @@
{% extends "base.html" %}
{% block title %}Central — Coming Soon{% endblock %}
{% block content %}
<article>
<header>
<h1>Central</h1>
</header>
<p>Data hub GUI — coming soon.</p>
</article>
{% endblock %}