""" Album - Documentation system. """ import os import httpx from pathlib import Path from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates app = FastAPI(title="Album", version="0.1.0") BASE_DIR = Path(__file__).parent.resolve() BOOK_DIR = BASE_DIR / "book" STATIC_DIR = BASE_DIR / "static" # Create static directory if it doesn't exist STATIC_DIR.mkdir(exist_ok=True) templates = Jinja2Templates(directory=str(BASE_DIR)) # Serve static files app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static") # Pawprint URL for data fetching PAWPRINT_URL = os.getenv("PAWPRINT_URL", "http://localhost:12000") def get_data(): """Fetch data from pawprint hub.""" try: resp = httpx.get(f"{PAWPRINT_URL}/api/data/album", timeout=5.0) if resp.status_code == 200: return resp.json() except Exception as e: print(f"Failed to fetch data from pawprint: {e}") return {"templates": [], "larders": [], "books": []} @app.get("/health") def health(): return {"status": "ok", "service": "album"} @app.get("/") def index(request: Request): data = get_data() return templates.TemplateResponse("index.html", { "request": request, "pawprint_url": os.getenv("PAWPRINT_EXTERNAL_URL", PAWPRINT_URL), **data, }) @app.get("/api/data") def api_data(): """API endpoint for frontend data (proxied from pawprint).""" return get_data() # --- Book: Feature Flow (HTML presentations) --- @app.get("/book/feature-flow/", response_class=HTMLResponse) @app.get("/book/feature-flow", response_class=HTMLResponse) def feature_flow_index(): """Redirect to English presentation by default""" return """ Feature Flow

Feature Flow - Standardization Pipeline

""" @app.get("/book/feature-flow/en", response_class=HTMLResponse) def feature_flow_en(): html_file = BOOK_DIR / "feature-flow" / "index-en.html" return HTMLResponse(html_file.read_text()) @app.get("/book/feature-flow/es", response_class=HTMLResponse) def feature_flow_es(): html_file = BOOK_DIR / "feature-flow" / "index-es.html" return HTMLResponse(html_file.read_text()) # --- Book: Feature Form Samples (templated book) --- @app.get("/book/feature-form-samples/", response_class=HTMLResponse) @app.get("/book/feature-form-samples", response_class=HTMLResponse) def feature_form_samples_index(request: Request): """Templated book landing page""" data = get_data() book = next((b for b in data.get("books", []) if b["slug"] == "feature-form-samples"), None) if not book: return HTMLResponse("

Book not found

", status_code=404) return templates.TemplateResponse("book-template.html", { "request": request, "book": book, }) @app.get("/book/feature-form-samples/template/", response_class=HTMLResponse) @app.get("/book/feature-form-samples/template", response_class=HTMLResponse) def feature_form_samples_template(): """View the template - styled like actual feature forms""" html = """ Feature Form Template · Album

Feature Form Template

Template

[Nombre del Flujo]

[Dueno de mascota / Veterinario / Admin]
[Que pagina/boton/link]
[Objetivo en una oracion]
  1. [Primera cosa que hace el usuario]
  2. [Segunda cosa que hace el usuario]
  3. [etc.]
[Resultado esperado cuando todo funciona]
[Problema 1]
[Problema 2]
[Caso especial 1]
[Caso especial 2]
[Otros flujos que se conectan con este]
[Notas para el equipo de desarrollo]
""" return HTMLResponse(html) @app.get("/book/feature-form-samples/larder/", response_class=HTMLResponse) @app.get("/book/feature-form-samples/larder", response_class=HTMLResponse) def feature_form_samples_larder(): """Browse the larder (actual data)""" html_file = BOOK_DIR / "feature-form-samples" / "index.html" if html_file.exists(): return HTMLResponse(html_file.read_text()) return HTMLResponse("

Larder index not found

", status_code=404) @app.get("/book/feature-form-samples/larder/{user_type}/{filename}", response_class=HTMLResponse) def feature_form_samples_detail(request: Request, user_type: str, filename: str): """View a specific feature form""" # Look in the larder subfolder (feature-form) larder_dir = BOOK_DIR / "feature-form-samples" / "feature-form" file_path = larder_dir / user_type / filename if not file_path.exists(): return HTMLResponse("

Not found

", status_code=404) content = file_path.read_text() detail_file = BOOK_DIR / "feature-form-samples" / "detail.html" return templates.TemplateResponse(str(detail_file.relative_to(BASE_DIR)), { "request": request, "user_type": user_type, "filename": filename, "content": content, }) # --- Book: Gherkin Samples --- @app.get("/book/gherkin-samples/", response_class=HTMLResponse) @app.get("/book/gherkin-samples", response_class=HTMLResponse) @app.get("/book/gherkin/", response_class=HTMLResponse) # Alias @app.get("/book/gherkin", response_class=HTMLResponse) # Alias def gherkin_samples_index(): """Browse gherkin samples""" html_file = BOOK_DIR / "gherkin-samples" / "index.html" return HTMLResponse(html_file.read_text()) @app.get("/book/gherkin-samples/{lang}/{user_type}/{filename}", response_class=HTMLResponse) @app.get("/book/gherkin/{lang}/{user_type}/{filename}", response_class=HTMLResponse) # Alias def gherkin_samples_detail(request: Request, lang: str, user_type: str, filename: str): """View a specific gherkin file""" file_path = BOOK_DIR / "gherkin-samples" / lang / user_type / filename if not file_path.exists() or not file_path.suffix == ".feature": return HTMLResponse("

Not found

", status_code=404) content = file_path.read_text() detail_file = BOOK_DIR / "gherkin-samples" / "detail.html" return templates.TemplateResponse(str(detail_file.relative_to(BASE_DIR)), { "request": request, "lang": lang, "user_type": user_type, "filename": filename, "content": content, }) # --- Book: Architecture Model (static site) --- app.mount("/book/arch-model", StaticFiles(directory=str(BOOK_DIR / "arch-model"), html=True), name="arch-model") # --- Book: Drive Index --- @app.get("/book/drive-index/", response_class=HTMLResponse) @app.get("/book/drive-index", response_class=HTMLResponse) def drive_index(): """Browse drive index""" html_file = BOOK_DIR / "drive-index" / "index.html" return HTMLResponse(html_file.read_text()) if __name__ == "__main__": import uvicorn uvicorn.run( "main:app", host="0.0.0.0", port=int(os.getenv("PORT", "12002")), reload=os.getenv("DEV", "").lower() in ("1", "true"), )