Initial commit: note-taking/task-tracking app with LLM integration scaffold
Vue 3 + TypeScript frontend with Pinia stores, markdown rendering (marked + DOMPurify), wikilink/tag linkification, and autocomplete. Quart async backend with SQLAlchemy 2.0, PostgreSQL ARRAY columns, task-note companion linking, backlinks, and note-to-task conversion. Docker Compose setup with PostgreSQL 16 and Ollama. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from quart import Quart, jsonify, make_response, request, send_from_directory
|
||||
|
||||
from fabledassistant.config import Config
|
||||
from fabledassistant.routes.api import api
|
||||
from fabledassistant.routes.notes import notes_bp
|
||||
from fabledassistant.routes.tasks import tasks_bp
|
||||
|
||||
STATIC_DIR = Path(__file__).parent / "static"
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def create_app() -> Quart:
|
||||
app = Quart(__name__, static_folder=None)
|
||||
app.secret_key = Config.SECRET_KEY
|
||||
|
||||
app.register_blueprint(api)
|
||||
app.register_blueprint(notes_bp)
|
||||
app.register_blueprint(tasks_bp)
|
||||
|
||||
@app.route("/")
|
||||
async def serve_index():
|
||||
resp = await make_response(
|
||||
await send_from_directory(STATIC_DIR, "index.html")
|
||||
)
|
||||
resp.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
|
||||
return resp
|
||||
|
||||
@app.errorhandler(404)
|
||||
async def handle_404(error):
|
||||
# Return JSON 404 for API routes
|
||||
if request.path.startswith("/api/"):
|
||||
return jsonify({"error": "Not found"}), 404
|
||||
# Try to serve static file
|
||||
path = request.path.lstrip("/")
|
||||
file_path = STATIC_DIR / path
|
||||
if path and file_path.is_file():
|
||||
return await send_from_directory(STATIC_DIR, path)
|
||||
# SPA fallback
|
||||
resp = await make_response(
|
||||
await send_from_directory(STATIC_DIR, "index.html")
|
||||
)
|
||||
resp.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
|
||||
return resp
|
||||
|
||||
@app.errorhandler(500)
|
||||
async def handle_500(error):
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
logger.exception("Internal server error on %s %s", request.method, request.path)
|
||||
if request.path.startswith("/api/"):
|
||||
return jsonify({"error": str(error)}), 500
|
||||
return "Internal Server Error", 500
|
||||
|
||||
return app
|
||||
Reference in New Issue
Block a user