Fix favicon not showing issue

- Use url_for() for all favicon and icon references in layout.html
- Add specific routes for favicon files to ensure proper serving
- Create dynamic webmanifest route with correct icon paths
- Import send_from_directory for serving static files
- This ensures favicons work correctly in all deployment scenarios
This commit is contained in:
2025-07-14 11:11:50 +02:00
committed by Jens Luedicke
parent 4fcf4bbf80
commit 4264357d04
9 changed files with 65 additions and 17 deletions

43
app.py
View File

@@ -1,4 +1,4 @@
from flask import Flask, render_template, request, redirect, url_for, jsonify, flash, session, g, Response, send_file, abort
from flask import Flask, render_template, request, redirect, url_for, jsonify, flash, session, g, Response, send_file, abort, send_from_directory
from flask_migrate import Migrate
from models import db, TimeEntry, WorkConfig, User, SystemSettings, Team, Role, Project, Company, CompanyWorkConfig, CompanySettings, UserPreferences, WorkRegion, AccountType, ProjectCategory, Task, SubTask, TaskStatus, TaskPriority, TaskDependency, Sprint, SprintStatus, Announcement, SystemEvent, WidgetType, UserDashboard, DashboardWidget, WidgetTemplate, Comment, CommentVisibility, BrandingSettings, CompanyInvitation, Note, NoteFolder, NoteShare
from data_formatting import (
@@ -397,6 +397,47 @@ def sitemap_xml():
return Response(sitemap_xml, mimetype='application/xml')
@app.route('/site.webmanifest')
def serve_webmanifest():
"""Serve web manifest with correct icon paths"""
manifest = {
"name": "TimeTrack",
"short_name": "TimeTrack",
"icons": [
{
"src": url_for('static', filename='android-chrome-192x192.png'),
"sizes": "192x192",
"type": "image/png"
},
{
"src": url_for('static', filename='android-chrome-512x512.png'),
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#667eea",
"background_color": "#ffffff",
"display": "standalone"
}
return jsonify(manifest)
# Favicon routes for compatibility
@app.route('/favicon.ico')
def favicon():
return send_from_directory(app.static_folder, 'favicon.ico', mimetype='image/x-icon')
@app.route('/favicon-32x32.png')
def favicon_32():
return send_from_directory(app.static_folder, 'favicon-32x32.png', mimetype='image/png')
@app.route('/favicon-16x16.png')
def favicon_16():
return send_from_directory(app.static_folder, 'favicon-16x16.png', mimetype='image/png')
@app.route('/apple-touch-icon.png')
def apple_touch_icon():
return send_from_directory(app.static_folder, 'apple-touch-icon.png', mimetype='image/png')
@app.route('/')
def home():
if g.user:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
static/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
static/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

BIN
static/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 B

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

1
static/site.webmanifest Normal file
View File

@@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

View File

@@ -54,6 +54,12 @@
{% endif %}
{% if g.branding and g.branding.favicon_filename %}
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='uploads/branding/' + g.branding.favicon_filename) }}">
{% else %}
<link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('static', filename='apple-touch-icon.png') }}">
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon-32x32.png') }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon-16x16.png') }}">
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}">
<link rel="manifest" href="{{ url_for('static', filename='site.webmanifest') }}">
{% endif %}
<style>
:root {