diff --git a/app.py b/app.py
index aca29fb..ca28295 100644
--- a/app.py
+++ b/app.py
@@ -6,7 +6,7 @@ from typing import Optional
import requests
from fastapi import FastAPI, File, Form, HTTPException, UploadFile
-from fastapi.responses import HTMLResponse, PlainTextResponse
+from fastapi.responses import HTMLResponse, PlainTextResponse, Response
API_BASE = os.getenv("API_BASE", "http://gx10.aquantico.lan:8093").rstrip("/")
OLLAMA_BASE_URL = os.getenv("OLLAMA_BASE_URL", "http://gx10.aquantico.lan:11434").rstrip("/")
@@ -93,29 +93,46 @@ def init_db():
def layout(title: str, body: str) -> str:
return f"""
-
+
+
+
+
+
+
+
{title}
+small{{color:var(--muted)}}
+.hint{{color:var(--muted);font-size:13px}}
+@media (max-width:900px){{nav{{width:86px;padding:10px}} nav a span{{display:none}} .brand{{font-size:12px}} main{{padding:12px}}}}
+
+
+
{body}
@@ -143,6 +160,40 @@ def startup():
init_db()
+@app.get("/manifest.webmanifest")
+def manifest():
+ return {
+ "name": "Audio Copilot",
+ "short_name": "Copilot",
+ "start_url": "/",
+ "display": "standalone",
+ "background_color": "#020617",
+ "theme_color": "#0f172a",
+ "icons": [
+ {"src": "/icon.svg", "sizes": "any", "type": "image/svg+xml", "purpose": "any maskable"}
+ ],
+ }
+
+
+@app.get("/icon.svg")
+def icon_svg():
+ svg = """"""
+ return Response(content=svg, media_type="image/svg+xml")
+
+
+@app.get("/sw.js")
+def sw_js():
+ js = """
+self.addEventListener('install', (event) => { self.skipWaiting(); });
+self.addEventListener('activate', (event) => { event.waitUntil(clients.claim()); });
+self.addEventListener('fetch', (event) => {
+ if (event.request.method !== 'GET') return;
+ event.respondWith(fetch(event.request).catch(() => new Response('offline', {status: 503})));
+});
+"""
+ return Response(content=js, media_type="application/javascript")
+
+
@app.get("/healthz")
def healthz():
return {"ok": True, "api_base": API_BASE, "ollama_base_url": OLLAMA_BASE_URL, "ollama_model": OLLAMA_MODEL, "db_path": DB_PATH}