From b1878e470fa4c78f14133841da68f0ce77b77bc6 Mon Sep 17 00:00:00 2001 From: Sergey Vanyushkin Date: Sat, 2 May 2026 16:23:57 +0300 Subject: [PATCH] feat(ui): add error handling, flash messages and SEO optimization - Add custom error pages (404, 403, 500) with user-friendly messages - Add flash message system with signed cookies for security - Add toast notifications with auto-dismiss and manual close - Add comprehensive SEO meta tags (description, keywords, OG, Twitter) - Add canonical URLs for SEO - Update routes to use slug-based URLs (/posts/{slug} instead of /posts/{id}) - Add Open Graph and Twitter Card meta tags for social sharing - Add favicon SVG - Update all templates with proper meta tags and URLs - Add error handlers registration in main.py - Add flash middleware for request handling - Install itsdangerous dependency --- app/main.py | 10 + app/presentation/templates/base.html | 155 ++++++++++++++- app/presentation/templates/pages/error.html | 111 +++++++++++ app/presentation/templates/pages/index.html | 13 +- .../templates/pages/post_detail.html | 16 +- .../templates/pages/post_form.html | 8 +- app/presentation/web/__init__.py | 3 +- app/presentation/web/error_handlers.py | 188 ++++++++++++++++++ app/presentation/web/flash.py | 160 +++++++++++++++ app/presentation/web/routes.py | 51 ++--- pyproject.toml | 1 + static/images/favicon.svg | 4 + static/js/flash.js | 69 +++++++ 13 files changed, 747 insertions(+), 42 deletions(-) create mode 100644 app/presentation/templates/pages/error.html create mode 100644 app/presentation/web/error_handlers.py create mode 100644 app/presentation/web/flash.py create mode 100644 static/images/favicon.svg create mode 100644 static/js/flash.js diff --git a/app/main.py b/app/main.py index 8483cd8..c721d75 100644 --- a/app/main.py +++ b/app/main.py @@ -26,6 +26,8 @@ from app.infrastructure.di.providers import ( from app.presentation import router from app.presentation.web import auth_router from app.presentation.web import router as web_router +from app.presentation.web.error_handlers import register_error_handlers +from app.presentation.web.flash import setup_flash_manager @asynccontextmanager @@ -71,6 +73,14 @@ def app_factory() -> FastAPI: setup_dishka(container, app) register_exception_handlers(app) + register_error_handlers(app) + + @app.middleware("http") + async def flash_middleware(request, call_next): + """Middleware to setup flash manager for each request.""" + await setup_flash_manager(request) + response = await call_next(request) + return response app.add_middleware( CORSMiddleware, diff --git a/app/presentation/templates/base.html b/app/presentation/templates/base.html index 14966c3..ce9aaa9 100644 --- a/app/presentation/templates/base.html +++ b/app/presentation/templates/base.html @@ -1,9 +1,35 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + {% block title %}Blog{% endblock %} @@ -17,6 +43,18 @@ {% include "partials/header.html" %} + + {% if flash_messages %} +
+ {% for msg in flash_messages %} + + {% endfor %} +
+ {% endif %} +
{% block content %}{% endblock %} @@ -26,6 +64,119 @@ {% include "partials/footer.html" %} + {% block extra_js %}{% endblock %} + + diff --git a/app/presentation/templates/pages/error.html b/app/presentation/templates/pages/error.html new file mode 100644 index 0000000..5454145 --- /dev/null +++ b/app/presentation/templates/pages/error.html @@ -0,0 +1,111 @@ +{% extends "base.html" %} + +{% block title %}{{ error_code }} - {{ error_title }}{% endblock %} +{% block meta_description %}{{ error_message }}{% endblock %} + +{% block content %} +
+
+
+ {% if error_code == 404 %} + 🔍 + {% elif error_code == 403 %} + 🚫 + {% elif error_code == 500 %} + ⚠️ + {% else %} + ❌ + {% endif %} +
+ +

{{ error_code }}

+

{{ error_title }}

+

{{ error_message }}

+ +
+ + + + + Go Home + + + {% if error_code == 403 %} + + Sign In + + {% endif %} + + +
+
+
+ + +{% endblock %} diff --git a/app/presentation/templates/pages/index.html b/app/presentation/templates/pages/index.html index e847b45..cbe67cd 100644 --- a/app/presentation/templates/pages/index.html +++ b/app/presentation/templates/pages/index.html @@ -1,6 +1,15 @@ {% extends "base.html" %} {% block title %}Blog - Home{% endblock %} +{% block meta_description %}Discover stories, thinking, and expertise from writers on any topic. A modern blog built with FastAPI.{% endblock %} +{% block meta_keywords %}blog, articles, posts, writing, fastapi, python{% endblock %} + +{% block og_type %}website{% endblock %} +{% block og_title %}Blog - Home{% endblock %} +{% block og_description %}Discover stories, thinking, and expertise from writers on any topic.{% endblock %} + +{% block twitter_title %}Blog - Home{% endblock %} +{% block twitter_description %}Discover stories, thinking, and expertise from writers on any topic.{% endblock %} {% block content %} - @@ -81,7 +81,7 @@