Skip to content

Backend-Übersicht

Audience: Dev
You will learn: - Flask-Anwendungsarchitektur und Module - API-Endpunkte und Datenfluss - File-System-Integration und Metadaten-Verwaltung - Backend-Services und Datenverarbeitung

Pre-requisites: - Architektur-Übersicht verstanden - Python und Flask Grundkenntnisse - Entwickler-Setup abgeschlossen

Anwendungsarchitektur

Flask-Application Structure

# app.py - Hauptanwendung
from flask import Flask, render_template, jsonify
import os
import json

app = Flask(__name__)

# Kernfunktionen:
# 1. Icon-Metadaten laden
# 2. File-System-Scanning  
# 3. REST API bereitstellen
# 4. Web-Interface rendern

Evidenz: app.py:1-67

Module und Dependencies

# pyproject.toml
[project]
name = "repl-nix-workspace"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
    "flask>=3.1.1",
]

Core Dependencies: - Flask 3.1.1+: Web-Framework und Template-Engine - Python 3.11+: Runtime-Environment - JSON (stdlib): Metadata-Parsing - OS (stdlib): File-System-Operations

Evidenz: pyproject.toml:1-8

API-Endpunkte

1. Web-Interface Endpunkt

@app.route('/')
def index():
    """Main page showing icon grid"""
    icons, categories = get_icon_list()
    return render_template('index.html', 
                         icons=icons, 
                         categories=categories, 
                         total_icons=len(icons))

Funktionalität: - Lädt komplette Icon-Liste mit Metadaten - Rendert HTML-Template mit Jinja2 - Übergibt Icon-Kategorien für Filterung

Performance: Template-Rendering + Icon-Scanning ~50-100ms

Evidenz: app.py:45-49

2. JSON API Endpunkt

@app.route('/api/icons')
def api_icons():
    """API endpoint to get icons as JSON"""
    icons, categories = get_icon_list()
    return jsonify({'icons': icons, 'categories': categories})

Response Format:

{
  "icons": [
    {
      "name": "home",
      "filename": "home.svg", 
      "path": "/static/icons/home.svg",
      "display_name": "Home",
      "category": "Navigation & Direction"
    }
  ],
  "categories": {
    "Navigation & Direction": ["home.svg", "user.svg"]
  }
}

Performance: JSON-Serialisierung ~10-30ms für 162 Icons

Evidenz: app.py:51-55

3. Single Icon Endpunkt

@app.route('/icon/<icon_name>')
def get_icon(icon_name):
    """Get individual icon details"""
    icons, _ = get_icon_list()
    icon = next((i for i in icons if i['name'] == icon_name), None)
    if icon:
        return jsonify(icon)
    return jsonify({'error': 'Icon not found'}), 404

Use Cases: - Programmatischer Zugriff auf einzelne Icons - Icon-Validation vor Integration - Metadaten-Abfrage für specific Icons

Security: Input-Validation gegen verfügbare Icon-Liste

Evidenz: app.py:57-64

Datenverarbeitung

Icon-Metadaten Laden

def load_icon_categories():
    """Load icon categories from icons.json"""
    try:
        with open('icons.json', 'r') as f:
            return json.load(f)
    except FileNotFoundError:
        return {}

Verhalten: - Erfolg: Lädt 20+ Kategorien mit Icon-Mappings - Fehler: Graceful fallback zu leeren Kategorien - Performance: File-read + JSON-parse ~1-5ms

Evidenz: app.py:7-13

File-System Integration

def get_icon_list():
    """Get list of all available icons from static/icons directory"""
    icons_dir = os.path.join('static', 'icons')
    if not os.path.exists(icons_dir):
        return [], {}

    # Create reverse mapping: filename -> category
    filename_to_category = {}
    for category, filenames in categories.items():
        for filename in filenames:
            filename_to_category[filename] = category

    icons = []
    for filename in os.listdir(icons_dir):
        if filename.endswith('.svg'):
            icon_name = filename[:-4]  # Remove .svg extension
            category = filename_to_category.get(filename, 'Uncategorized')
            icons.append({
                'name': icon_name,
                'filename': filename,
                'path': f'/static/icons/{filename}',
                'display_name': icon_name.replace('-', ' ').title(),
                'category': category
            })

    return sorted(icons, key=lambda x: x['name']), categories

Datenfluss: 1. Directory Scan: os.listdir('static/icons') 2. Metadata Merge: JSON-Kategorien + File-System-Realität 3. Icon Enrichment: Display-Namen und Pfade generieren 4. Sorting: Alphabetische Sortierung für UI

Performance Characteristics: - File Count: 162 SVG-Dateien - Directory Scan: ~1-5ms bei SSD - Metadata Processing: ~5-10ms - Total Time: ~10-20ms per request

Evidenz: app.py:15-43

Datenstrukturen

Icon Object Schema

{
    'name': str,         # 'home' (ohne .svg)
    'filename': str,     # 'home.svg'
    'path': str,         # '/static/icons/home.svg'
    'display_name': str, # 'Home'
    'category': str      # 'Navigation & Direction'
}

Categories Schema

{
    "Navigation & Direction": [
        "arrow-up.svg",
        "arrow-down.svg", 
        # ...
    ],
    "UI Controls": [
        "plus.svg",
        "minus.svg",
        # ...
    ]
}

Evidenz: icons.json:1-206, app.py:30-42

Services und Business Logic

Icon Discovery Service

class IconService:
    """Service for icon discovery and metadata management"""

    @staticmethod
    def get_all_icons():
        """Returns all icons with metadata"""
        return get_icon_list()

    @staticmethod  
    def find_icon(name):
        """Find specific icon by name"""
        icons, _ = get_icon_list()
        return next((i for i in icons if i['name'] == name), None)

    @staticmethod
    def get_categories():
        """Get all available categories"""
        return load_icon_categories()

File System Service

class FileSystemService:
    """Service for file system operations"""

    ICONS_DIR = 'static/icons'
    METADATA_FILE = 'icons.json'

    @classmethod
    def scan_icons(cls):
        """Scan file system for available icons"""
        if not os.path.exists(cls.ICONS_DIR):
            return []
        return [f for f in os.listdir(cls.ICONS_DIR) if f.endswith('.svg')]

    @classmethod
    def load_metadata(cls):
        """Load icon metadata from JSON"""
        try:
            with open(cls.METADATA_FILE, 'r') as f:
                return json.load(f)
        except FileNotFoundError:
            return {}

Evidenz: app.py service logic patterns

Error Handling

Graceful Degradation

# Metadata loading mit fallback
def load_icon_categories():
    try:
        with open('icons.json', 'r') as f:
            return json.load(f)
    except FileNotFoundError:
        app.logger.warning("icons.json not found, returning empty categories")
        return {}
    except json.JSONDecodeError:
        app.logger.error("icons.json invalid JSON, returning empty categories")
        return {}

# Directory scanning mit validation
def get_icon_list():
    icons_dir = os.path.join('static', 'icons')
    if not os.path.exists(icons_dir):
        app.logger.error(f"Icons directory {icons_dir} does not exist")
        return [], {}

HTTP Error Responses

# 404 für unbekannte Icons
@app.route('/icon/<icon_name>')
def get_icon(icon_name):
    icon = find_icon_by_name(icon_name)
    if not icon:
        return jsonify({'error': 'Icon not found'}), 404
    return jsonify(icon)

# 500 für System-Fehler (automatisch durch Flask)

Evidenz: app.py:57-64 error handling

Performance Optimierung

Caching Strategies

# In-Memory-Caching für Icon-Liste
from functools import lru_cache

@lru_cache(maxsize=1)
def get_cached_icon_list():
    """Cached version of icon list - invalidate on metadata changes"""
    return get_icon_list()

# Cache-Invalidierung bei Updates
def invalidate_icon_cache():
    get_cached_icon_list.cache_clear()

Database Migration Path

# Future: SQLite für größere Icon-Sammlungen
class IconRepository:
    def __init__(self, db_path='icons.db'):
        self.db_path = db_path
        self._init_db()

    def _init_db(self):
        """Initialize SQLite database for icons"""
        # CREATE TABLE icons (name, filename, category, path, metadata)
        pass

    def get_all_icons(self):
        """Get all icons from database"""
        # SELECT * FROM icons ORDER BY name
        pass

Migration Trigger: >500 Icons oder Performance-Probleme bei Directory-Scanning

Evidenz: replit.md:91 (Development Considerations)

Integration Points

Static File Serving

# Flask automatisches Static-File-Serving
# /static/icons/*.svg → direkter File-Access
# Kein Backend-Processing für SVG-Delivery

# Optional: Custom static file handler
@app.route('/static/icons/<filename>')
def serve_icon(filename):
    return send_from_directory('static/icons', filename, 
                             mimetype='image/svg+xml')

Template Integration

# Jinja2 Template-Variables
@app.route('/')
def index():
    context = {
        'icons': icons,
        'categories': categories,
        'total_icons': len(icons),
        'app_version': '1.0.0'
    }
    return render_template('index.html', **context)

Evidenz: app.py:45-49, templates/index.html integration

Development Tools

Debug Mode

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

Debug Features: - Auto-reload: Code-Änderungen triggern Neustart - Error Pages: Detaillierte Stack-Traces - Template Debugging: Jinja2-Variable-Inspection

Logging Configuration

import logging

# Optional: Structured logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

app.logger.setLevel(logging.INFO)

Health Checks

@app.route('/health')
def health_check():
    """System health check endpoint"""
    try:
        icons, categories = get_icon_list()
        return jsonify({
            'status': 'healthy',
            'icon_count': len(icons),
            'categories_count': len(categories),
            'timestamp': time.time()
        })
    except Exception as e:
        return jsonify({
            'status': 'unhealthy', 
            'error': str(e)
        }), 503

Evidenz: app.py:66-67 main execution

Testing Strategy

Unit Tests

import unittest
from app import load_icon_categories, get_icon_list

class TestIconService(unittest.TestCase):
    def test_load_categories(self):
        categories = load_icon_categories()
        self.assertIsInstance(categories, dict)
        self.assertGreater(len(categories), 10)

    def test_icon_list_format(self):
        icons, _ = get_icon_list()
        if icons:
            icon = icons[0]
            self.assertIn('name', icon)
            self.assertIn('filename', icon)
            self.assertIn('category', icon)

Integration Tests

def test_api_endpoints():
    with app.test_client() as client:
        # Test main page
        response = client.get('/')
        assert response.status_code == 200

        # Test API
        response = client.get('/api/icons')
        assert response.status_code == 200
        data = response.get_json()
        assert 'icons' in data
        assert 'categories' in data

Nächste Schritte: - Frontend-Dokumentation für UI-Integration - API-Referenz für externe Nutzung - Operations-Runbook für Produktivbetrieb