Compare commits

...

4 Commits

Author SHA1 Message Date
fd1d5c4f31 icons
All checks were successful
ci/woodpecker/push/predeploy Pipeline was successful
ci/woodpecker/push/build/4 Pipeline was successful
ci/woodpecker/push/build/3 Pipeline was successful
ci/woodpecker/push/build/1 Pipeline was successful
ci/woodpecker/push/build/2 Pipeline was successful
ci/woodpecker/push/deploy/4 Pipeline was successful
ci/woodpecker/push/deploy/1 Pipeline was successful
ci/woodpecker/push/deploy/3 Pipeline was successful
ci/woodpecker/push/deploy/2 Pipeline was successful
ci/woodpecker/tag/predeploy Pipeline was successful
ci/woodpecker/tag/build/4 Pipeline was successful
ci/woodpecker/tag/build/1 Pipeline was successful
ci/woodpecker/tag/build/3 Pipeline was successful
ci/woodpecker/tag/build/2 Pipeline was successful
ci/woodpecker/tag/deploy/4 Pipeline was successful
ci/woodpecker/tag/deploy/1 Pipeline was successful
ci/woodpecker/tag/deploy/3 Pipeline was successful
ci/woodpecker/tag/deploy/2 Pipeline was successful
2025-11-30 18:01:12 +01:00
51072424ed Apple Touch Icons added 3
All checks were successful
ci/woodpecker/push/build/2 Pipeline was successful
ci/woodpecker/push/build/3 Pipeline was successful
ci/woodpecker/push/predeploy Pipeline was successful
ci/woodpecker/push/build/1 Pipeline was successful
ci/woodpecker/push/build/4 Pipeline was successful
ci/woodpecker/push/deploy/3 Pipeline was successful
ci/woodpecker/push/deploy/1 Pipeline was successful
ci/woodpecker/push/deploy/2 Pipeline was successful
ci/woodpecker/push/deploy/4 Pipeline was successful
ci/woodpecker/tag/predeploy Pipeline was successful
ci/woodpecker/tag/build/4 Pipeline was successful
ci/woodpecker/tag/build/1 Pipeline was successful
ci/woodpecker/tag/build/3 Pipeline was successful
ci/woodpecker/tag/build/2 Pipeline was successful
ci/woodpecker/tag/deploy/2 Pipeline was successful
ci/woodpecker/tag/deploy/1 Pipeline was successful
ci/woodpecker/tag/deploy/3 Pipeline was successful
ci/woodpecker/tag/deploy/4 Pipeline was successful
2025-11-30 17:03:14 +01:00
722f4f0a8c Apple Touch Icons added 2
All checks were successful
ci/woodpecker/push/build/4 Pipeline was successful
ci/woodpecker/push/build/2 Pipeline was successful
ci/woodpecker/push/build/3 Pipeline was successful
ci/woodpecker/push/build/1 Pipeline was successful
ci/woodpecker/push/predeploy Pipeline was successful
ci/woodpecker/push/deploy/2 Pipeline was successful
ci/woodpecker/push/deploy/4 Pipeline was successful
ci/woodpecker/push/deploy/3 Pipeline was successful
ci/woodpecker/push/deploy/1 Pipeline was successful
2025-11-30 16:58:08 +01:00
0acabc737e Apple Touch Icons added
All checks were successful
ci/woodpecker/push/build/4 Pipeline was successful
ci/woodpecker/push/build/2 Pipeline was successful
ci/woodpecker/push/build/1 Pipeline was successful
ci/woodpecker/push/build/3 Pipeline was successful
ci/woodpecker/push/predeploy Pipeline was successful
ci/woodpecker/push/deploy/3 Pipeline was successful
ci/woodpecker/push/deploy/4 Pipeline was successful
ci/woodpecker/push/deploy/2 Pipeline was successful
ci/woodpecker/push/deploy/1 Pipeline was successful
2025-11-30 16:54:47 +01:00
37 changed files with 283 additions and 1 deletions

View File

@@ -5,7 +5,7 @@ import os
from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.responses import HTMLResponse, JSONResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
@@ -49,6 +49,44 @@ static_dir.mkdir(exist_ok=True)
app.mount("/static", StaticFiles(directory=str(static_dir)), name="static")
@app.get("/apple-touch-icon.png")
async def apple_touch_icon():
"""Serve Apple Touch Icon with proper headers."""
icon_path = static_dir / "apple-touch-icon.png"
return FileResponse(
path=icon_path,
media_type="image/png",
headers={
"Cache-Control": "public, max-age=31536000",
"Content-Type": "image/png"
}
)
@app.get("/favicon.ico")
async def favicon():
"""Serve favicon."""
icon_path = static_dir / "apple-touch-icon.png"
return FileResponse(
path=icon_path,
media_type="image/png"
)
@app.get("/manifest.json")
async def manifest():
"""Serve Web App Manifest with proper headers."""
manifest_path = static_dir / "manifest.json"
return FileResponse(
path=manifest_path,
media_type="application/manifest+json",
headers={
"Cache-Control": "public, max-age=86400",
"Content-Type": "application/manifest+json"
}
)
@app.get("/health")
async def health() -> JSONResponse:
"""Health check endpoint for Kubernetes/Docker.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,4 @@
<svg width="180" height="180" viewBox="0 0 180 180" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="180" height="180" rx="40" fill="#667EEA"/>
<text x="90" y="130" font-size="80" text-anchor="middle" fill="white">🏡</text>
</svg>

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,4 @@
<svg width="180" height="180" viewBox="0 0 180 180" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="180" height="180" rx="40" fill="#667EEA"/>
<text x="90" y="130" font-size="80" text-anchor="middle" fill="white">🚗</text>
</svg>

After

Width:  |  Height:  |  Size: 244 B

View File

@@ -0,0 +1,43 @@
{
"name": "Home Automation",
"short_name": "Home",
"description": "Smart Home Automation System",
"start_url": "/",
"display": "standalone",
"background_color": "#667eea",
"theme_color": "#667eea",
"orientation": "portrait",
"icons": [
{
"src": "/static/apple-touch-icon-180x180.png",
"sizes": "180x180",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/static/apple-touch-icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "/static/apple-touch-icon-120x120.png",
"sizes": "120x120",
"type": "image/png"
},
{
"src": "/static/apple-touch-icon-76x76.png",
"sizes": "76x76",
"type": "image/png"
},
{
"src": "/static/apple-touch-icon-32x32.png",
"sizes": "32x32",
"type": "image/png"
},
{
"src": "/static/apple-touch-icon-16x16.png",
"sizes": "16x16",
"type": "image/png"
}
]
}

View File

@@ -4,7 +4,19 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home Automation</title>
<!-- Apple Touch Icon -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="152x152" href="/static/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="120x120" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="Dashboard">
<meta name="theme-color" content="#667eea">
<link rel="manifest" href="/static/manifest.json">
<style>
* {
margin: 0;

View File

@@ -4,6 +4,18 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gerät - Home Automation</title>
<!-- Apple Touch Icon -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="152x152" href="/static/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="120x120" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/apple-touch-icon.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="Gerät">
<meta name="theme-color" content="#667eea">
<link rel="manifest" href="/static/manifest.json">
<style>
* {
margin: 0;

View File

@@ -4,6 +4,19 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Garage - Home Automation</title>
<!-- Apple Touch Icon -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/garage-icon-180x180.png">
<link rel="apple-touch-icon" sizes="152x152" href="/static/garage-icon-152x152.png">
<link rel="apple-touch-icon" sizes="120x120" href="/static/garage-icon-120x120.png">
<link rel="apple-touch-icon" sizes="76x76" href="/static/garage-icon-76x76.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/garage-icon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/garage-icon-16x16.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="Garage">
<meta name="theme-color" content="#667eea">
<link rel="manifest" href="/static/manifest.json">
<style>
* {
margin: 0;

View File

@@ -4,6 +4,19 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home Automation</title>
<!-- Apple Touch Icon -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon-180x180.png">
<link rel="apple-touch-icon" sizes="152x152" href="/static/apple-touch-icon-152x152.png">
<link rel="apple-touch-icon" sizes="120x120" href="/static/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="76x76" href="/static/apple-touch-icon-76x76.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/apple-touch-icon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/apple-touch-icon-16x16.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="Home Automation">
<meta name="theme-color" content="#667eea">
<link rel="manifest" href="/static/manifest.json">
<style>
* {
margin: 0;

View File

@@ -4,6 +4,18 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ room_name }} - Home Automation</title>
<!-- Apple Touch Icon -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="152x152" href="/static/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="120x120" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/apple-touch-icon.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="{{ room_name }}">
<meta name="theme-color" content="#667eea">
<link rel="manifest" href="/static/manifest.json">
<style>
* {
margin: 0;

View File

@@ -4,6 +4,19 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Räume - Home Automation</title>
<!-- Apple Touch Icon -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon-180x180.png">
<link rel="apple-touch-icon" sizes="152x152" href="/static/apple-touch-icon-152x152.png">
<link rel="apple-touch-icon" sizes="120x120" href="/static/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="76x76" href="/static/apple-touch-icon-76x76.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/apple-touch-icon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/apple-touch-icon-16x16.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="Räume">
<meta name="theme-color" content="#667eea">
<link rel="manifest" href="/static/manifest.json">
<style>
* {
margin: 0;

30
create_icons.py Normal file
View File

@@ -0,0 +1,30 @@
"""
Script to create additional PNG icon sizes for better iOS compatibility
"""
import os
from pathlib import Path
from PIL import Image
def create_icon_sizes():
static_dir = Path("/Users/wn/Workspace/home-automation/apps/ui/static")
# Sizes that iOS might need
sizes = [16, 32, 57, 60, 72, 76, 114, 120, 144, 152, 180]
# Create home icons
base_icon = Image.open(static_dir / "apple-touch-icon.png")
for size in sizes:
resized = base_icon.resize((size, size), Image.Resampling.LANCZOS)
resized.save(static_dir / f"apple-touch-icon-{size}x{size}.png")
print(f"Created apple-touch-icon-{size}x{size}.png")
# Create garage icons
garage_icon = Image.open(static_dir / "garage-icon.png")
for size in sizes:
resized = garage_icon.resize((size, size), Image.Resampling.LANCZOS)
resized.save(static_dir / f"garage-icon-{size}x{size}.png")
print(f"Created garage-icon-{size}x{size}.png")
if __name__ == "__main__":
create_icon_sizes()

59
icon-generator.html Normal file
View File

@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>Icon Generator</title>
</head>
<body>
<canvas id="homeCanvas" width="180" height="180" style="border: 1px solid #ccc;"></canvas>
<canvas id="garageCanvas" width="180" height="180" style="border: 1px solid #ccc;"></canvas>
<br><br>
<button onclick="downloadHome()">Download Home Icon</button>
<button onclick="downloadGarage()">Download Garage Icon</button>
<script>
// Home Icon
const homeCanvas = document.getElementById('homeCanvas');
const homeCtx = homeCanvas.getContext('2d');
// Fill background
homeCtx.fillStyle = '#667EEA';
homeCtx.fillRect(0, 0, 180, 180);
// Add house emoji
homeCtx.font = '80px Arial';
homeCtx.fillStyle = 'white';
homeCtx.textAlign = 'center';
homeCtx.textBaseline = 'middle';
homeCtx.fillText('🏡', 90, 90);
// Garage Icon
const garageCanvas = document.getElementById('garageCanvas');
const garageCtx = garageCanvas.getContext('2d');
// Fill background
garageCtx.fillStyle = '#667EEA';
garageCtx.fillRect(0, 0, 180, 180);
// Add car emoji
garageCtx.font = '80px Arial';
garageCtx.fillStyle = 'white';
garageCtx.textAlign = 'center';
garageCtx.textBaseline = 'middle';
garageCtx.fillText('🚗', 90, 90);
function downloadHome() {
const link = document.createElement('a');
link.download = 'apple-touch-icon.png';
link.href = homeCanvas.toDataURL();
link.click();
}
function downloadGarage() {
const link = document.createElement('a');
link.download = 'garage-icon.png';
link.href = garageCanvas.toDataURL();
link.click();
}
</script>
</body>
</html>

29
test-icons.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/bash
# Script to test icon accessibility over HTTPS/mTLS
echo "Testing Apple Touch Icon accessibility..."
# Test base icons
echo "1. Testing main apple-touch-icon.png:"
curl -I "https://your-domain.com/static/apple-touch-icon-180x180.png" || echo "FAILED"
echo "2. Testing garage icon:"
curl -I "https://your-domain.com/static/garage-icon-180x180.png" || echo "FAILED"
echo "3. Testing manifest:"
curl -I "https://your-domain.com/manifest.json" || echo "FAILED"
echo "4. Testing favicon route:"
curl -I "https://your-domain.com/favicon.ico" || echo "FAILED"
echo "5. Testing apple-touch-icon route:"
curl -I "https://your-domain.com/apple-touch-icon.png" || echo "FAILED"
echo ""
echo "Testing mTLS with client certificate:"
echo "6. Testing with client cert:"
curl -I --cert client.crt --key client.key "https://your-domain.com/static/apple-touch-icon-180x180.png" || echo "FAILED"
echo ""
echo "Note: Replace 'your-domain.com' with your actual domain"
echo "Note: Use actual client certificate files if testing mTLS"