Joachim Hummel 042ae6ac6d Add Geofences navigation link for all ADMIN users
Fixed navigation access so that all users with ADMIN role can see
and access the Geofences menu item, not just the 'admin' user.

**Changes:**
- Added "Geofences" to navigation menu
- Set roles: ['ADMIN'] - accessible to all ADMIN users
- Set superAdminOnly: false - not restricted to 'admin' username

Now any user with ADMIN role can:
- Access /admin/geofences (management)
- Access /admin/geofences/events (event history)
- See geofence widget on dashboard
- View geofences on map

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 23:20:20 +00:00
2025-11-24 16:30:37 +00:00
2025-11-24 20:33:15 +00:00
2025-11-24 16:30:37 +00:00
2025-11-24 16:30:37 +00:00
2025-12-01 17:56:48 +00:00
2025-11-24 16:30:37 +00:00
2025-11-24 16:30:37 +00:00
2025-11-24 16:30:37 +00:00
2025-11-24 16:30:37 +00:00
2025-11-24 16:30:37 +00:00
2025-11-24 16:30:37 +00:00

Location Tracker - Next.js Anwendung

Eine moderne Location-Tracking Anwendung basierend auf Next.js 14 mit MQTT/OwnTracks Integration, SQLite-Datenbank, Admin-Panel und Authentifizierung.

📋 Inhaltsverzeichnis


Features

Öffentliche Features

  • 🗺️ Interaktive Karte - Echtzeit-Standortverfolgung mit Leaflet.js
  • 🎨 Mehrere Kartenansichten - Standard, Satellit, Dark Mode
  • 🔍 Device-Filterung - Filtern nach Gerät und Zeitraum
  • ⏱️ Flexible Zeitfilter:
    • Quick Filters: 1h, 3h, 6h, 12h, 24h, All
    • Custom Range: Benutzerdefinierter Zeitraum mit DateTime-Picker (z.B. 16.11.2025 16:00 - 17.11.2025 06:00)
    • Kompakte UI - Custom Range nur sichtbar wenn aktiviert
  • 🔄 Auto-Refresh - Automatische Aktualisierung alle 5 Sekunden mit Pause/Resume Button
  • 🎯 Auto-Center - Karte zentriert automatisch auf neueste Position
  • ⏸️ Pause/Resume - Toggle-Button zum Stoppen/Starten des Auto-Refresh
  • 📱 Responsive Design - Optimiert für Desktop und Mobile
  • 📊 Polylines - Bewegungspfade mit farbcodierter Darstellung
  • 🎨 Marker-Sortierung - Neueste Position immer im Vordergrund (z-index optimiert)
  • 📍 Zoom-basierte Icon-Skalierung - Marker passen sich automatisch an Zoom-Level an

Admin-Panel (Login erforderlich)

  • 🔐 Authentifizierung - NextAuth.js v5 mit bcrypt-Hashing
  • 📊 Dashboard - Übersicht über Geräte, Statistiken und Datenbankstatus
  • ⏱️ System Status - Live-Uptime, Memory Usage, Runtime Info
  • 📱 Device Management - Geräte hinzufügen, bearbeiten, löschen
  • 💾 Datenbank-Wartung:
    • 🧹 Cleanup alter Daten (7, 15, 30, 90 Tage)
    • Datenbank-Optimierung (VACUUM)
    • 📈 Detaillierte Statistiken
  • 🟢 Online/Offline Status - Echtzeit-Status (< 10 Min = Online)
  • 🔋 Telemetrie-Daten - Batterie, Geschwindigkeit, letzte Position (speed=0 wird korrekt behandelt)

🛠 Tech Stack

  • Framework: Next.js 14 (App Router)
  • Sprache: TypeScript 5.9
  • Styling: Tailwind CSS v4
  • Karten: Leaflet 1.9.4 + React-Leaflet 5.0
  • Authentifizierung: NextAuth.js v5 (beta)
  • Datenbank: SQLite (better-sqlite3)
  • Passwort-Hashing: bcryptjs
  • Datenquelle: MQTT Broker + lokale SQLite-Cache

Dual-Database Architektur

  • database.sqlite - User, Geräte (kritische Daten)
  • locations.sqlite - Location-Tracking (hohe Schreibrate, isoliert)

📦 Installation

Voraussetzungen

  • Node.js 18+
  • npm oder yarn

Schritte

  1. Repository klonen
git clone https://github.com/yourusername/location-tracker-app.git
cd location-tracker-app
  1. Dependencies installieren
npm install
  1. Datenbank initialisieren
npm run db:init

Dies erstellt:

  • data/database.sqlite (User + Devices)
  • data/locations.sqlite (Location-Tracking)
  • Standard Admin-User: admin / admin123
  • Standard Devices (ID 10, 11)
  1. Development Server starten
npm run dev
  1. Im Browser öffnen

🗄️ Datenbank-Setup

Initialisierung

Beide Datenbanken erstellen:

npm run db:init

Nur database.sqlite (User/Devices):

npm run db:init:app

Nur locations.sqlite (Tracking):

npm run db:init:locations

Datenbank zurücksetzen

Admin-User neu anlegen:

node scripts/reset-admin.js

Alte Locations löschen:

npm run db:cleanup       # Älter als 7 Tage
npm run db:cleanup:7d    # Älter als 7 Tage
npm run db:cleanup:30d   # Älter als 30 Tage

Duplikate entfernen (falls vorhanden):

node scripts/remove-duplicates.js

Schema

database.sqlite (User & Devices)

User Tabelle:

id              TEXT PRIMARY KEY
username        TEXT UNIQUE NOT NULL
email           TEXT
passwordHash    TEXT NOT NULL
role            TEXT NOT NULL DEFAULT 'VIEWER'  -- ADMIN oder VIEWER
parent_user_id  TEXT                            -- FK zu User.id (Hierarchie)
createdAt       TEXT DEFAULT (datetime('now'))
updatedAt       TEXT DEFAULT (datetime('now'))
lastLoginAt     TEXT

Device Tabelle:

id              TEXT PRIMARY KEY
name            TEXT NOT NULL
color           TEXT NOT NULL
ownerId         TEXT                            -- FK zu User.id
isActive        INTEGER DEFAULT 1               -- 0 oder 1
description     TEXT
icon            TEXT
createdAt       TEXT DEFAULT (datetime('now'))
updatedAt       TEXT DEFAULT (datetime('now'))

MQTT Credentials Tabelle:

id                  INTEGER PRIMARY KEY AUTOINCREMENT
device_id           TEXT NOT NULL UNIQUE            -- FK zu Device.id
mqtt_username       TEXT NOT NULL UNIQUE
mqtt_password_hash  TEXT NOT NULL
enabled             INTEGER DEFAULT 1               -- 0 oder 1
created_at          TEXT DEFAULT (datetime('now'))
updated_at          TEXT DEFAULT (datetime('now'))

MQTT ACL Rules Tabelle:

id              INTEGER PRIMARY KEY AUTOINCREMENT
device_id       TEXT NOT NULL                   -- FK zu Device.id
topic_pattern   TEXT NOT NULL
permission      TEXT NOT NULL                   -- 'read', 'write', 'readwrite'
created_at      TEXT DEFAULT (datetime('now'))

MQTT Sync Status Tabelle:

id                  INTEGER PRIMARY KEY CHECK (id = 1)  -- Singleton
pending_changes     INTEGER DEFAULT 0
last_sync_at        TEXT
last_sync_status    TEXT
created_at          TEXT DEFAULT (datetime('now'))
updated_at          TEXT DEFAULT (datetime('now'))

Indexes:

  • idx_user_username ON User(username)
  • idx_user_parent ON User(parent_user_id)
  • idx_device_owner ON Device(ownerId)
  • idx_device_active ON Device(isActive)
  • idx_mqtt_credentials_device ON mqtt_credentials(device_id)
  • idx_mqtt_credentials_username ON mqtt_credentials(mqtt_username)
  • idx_mqtt_acl_device ON mqtt_acl_rules(device_id)

locations.sqlite (Tracking Data)

Location Tabelle:

id              INTEGER PRIMARY KEY AUTOINCREMENT
latitude        REAL NOT NULL                   -- -90 bis +90
longitude       REAL NOT NULL                   -- -180 bis +180
timestamp       TEXT NOT NULL                   -- ISO 8601 format
user_id         INTEGER DEFAULT 0
first_name      TEXT
last_name       TEXT
username        TEXT                            -- Device Tracker ID
marker_label    TEXT
display_time    TEXT                            -- Formatierte Zeit für UI
chat_id         INTEGER DEFAULT 0
battery         INTEGER                         -- Batteriestand in %
speed           REAL                            -- Geschwindigkeit in km/h
created_at      TEXT DEFAULT (datetime('now'))

Indexes:

  • idx_location_timestamp ON Location(timestamp DESC)
  • idx_location_username ON Location(username)
  • idx_location_user_id ON Location(user_id)
  • idx_location_composite ON Location(user_id, username, timestamp DESC)
  • idx_location_unique UNIQUE ON Location(timestamp, username, latitude, longitude)

Constraints:

  • Latitude: -90 bis +90
  • Longitude: -180 bis +180
  • UNIQUE: Kombination aus timestamp, username, latitude, longitude verhindert Duplikate

WAL Mode: Beide Datenbanken nutzen Write-Ahead Logging für bessere Concurrency


🚀 Verwendung

Login

Standard-Zugangsdaten:

Benutzername: admin
Passwort: admin123

⚠️ Wichtig: Für Production neuen User anlegen und Passwort ändern!

Geräte hinzufügen

  1. Admin-Panel öffnen: /admin/devices
  2. "Add Device" klicken
  3. Device ID (muss mit OwnTracks tid übereinstimmen)
  4. Name und Farbe festlegen
  5. Speichern

Wichtig: Die Device ID muss mit der OwnTracks Tracker-ID übereinstimmen!

OwnTracks konfigurieren

In der OwnTracks App:

  • Tracker ID (tid): z.B. 12
  • Topic: OwnTracks publishes automatically to owntracks/<username>/<device_id>
    • Example: owntracks/device_12_4397af93/12
  • MQTT Broker konfigurieren (siehe MQTT Setup)

Die App empfängt die Daten direkt vom MQTT Broker.

Zeitfilter verwenden

Die App bietet zwei Modi für die Zeitfilterung:

Quick Filters (Schnellauswahl)

Vordefinierte Zeiträume für schnellen Zugriff:

  • 1 Hour - Locations der letzten Stunde
  • 3 Hours - Locations der letzten 3 Stunden
  • 6 Hours - Locations der letzten 6 Stunden
  • 12 Hours - Locations der letzten 12 Stunden
  • 24 Hours - Locations der letzten 24 Stunden
  • All - Alle verfügbaren Locations

Verwendung:

  1. Im Header unter "Time:" gewünschten Zeitraum auswählen
  2. Die Karte aktualisiert sich automatisch

Custom Range (Benutzerdefiniert)

Für spezifische Zeiträume, z.B. "Route von gestern Abend 18:00 bis heute Morgen 08:00":

Verwendung:

  1. Auf den "📅 Custom" Button klicken
  2. Custom Range Felder erscheinen:
    • From: Start-Datum und -Zeit wählen (z.B. 16.11.2025 16:00)
    • To: End-Datum und -Zeit wählen (z.B. 17.11.2025 06:00)
  3. Die Route wird automatisch für den gewählten Zeitraum angezeigt
  4. Zum Zurückschalten: "📅 Quick" Button klicken

Hinweis: Custom Range Controls sind nur sichtbar wenn aktiviert - spart Platz im Header!


🏗 Architektur

Datenfluss

flowchart TD
    A[📱 OwnTracks App] -->|MQTT Publish| B[🔌 MQTT Broker]
    B -->|Subscribe| C[📡 Next.js MQTT Subscriber]

    C -->|Store Locations| D[(🗄️ SQLite Cache<br/>locations.sqlite)]

    E[🖥️ Browser Client] -->|GET /api/locations<br/>alle 5 Sek| F[📡 Next.js API Route]

    D -->|Query Filtered Data| F
    F -->|JSON Response| E

    E -->|Render| G[🗺️ React Leaflet Map]

    H[👤 Admin User] -->|Login| I[🔐 NextAuth.js]
    I -->|Authenticated| J[📊 Admin Panel]
    J -->|CRUD Operations| K[(💼 SQLite DB<br/>database.sqlite)]

    style A fill:#4CAF50
    style B fill:#FF9800
    style C fill:#2196F3
    style D fill:#FFC107
    style F fill:#00BCD4
    style G fill:#8BC34A
    style I fill:#E91E63
    style K fill:#FFC107

Komponenten-Übersicht

graph LR
    subgraph "External Services"
        A[OwnTracks App]
        B[MQTT Broker]
    end

    subgraph "Next.js Application"
        C[MQTT Subscriber]
        D[Frontend<br/>React/Leaflet]
        E[API Routes]
        F[Auth Layer<br/>NextAuth.js]
    end

    subgraph "Data Layer"
        G[locations.sqlite<br/>Tracking Data]
        H[database.sqlite<br/>Users & Devices]
    end

    A -->|MQTT| B
    B -->|Subscribe| C
    C -->|Write| G

    D -->|HTTP| E
    E -->|Read/Write| G
    E -->|Read/Write| H

    D -->|Auth| F
    F -->|Validate| H

    style A fill:#4CAF50,color:#fff
    style B fill:#FF9800,color:#fff
    style C fill:#2196F3,color:#fff
    style D fill:#00BCD4,color:#000
    style E fill:#00BCD4,color:#000
    style F fill:#E91E63,color:#fff
    style G fill:#FFC107,color:#000
    style H fill:#FFC107,color:#000

Datenbank-Architektur

erDiagram
    USER ||--o{ USER : "parent_user_id"
    USER ||--o{ DEVICE : owns
    DEVICE ||--o{ LOCATION : tracks
    DEVICE ||--o| MQTT_CREDENTIALS : has
    DEVICE ||--o{ MQTT_ACL_RULES : has

    USER {
        string id PK
        string username UK
        string email
        string passwordHash
        string role
        string parent_user_id FK
        datetime createdAt
        datetime lastLoginAt
    }

    DEVICE {
        string id PK
        string name
        string color
        string ownerId FK
        boolean isActive
        string description
        datetime createdAt
    }

    MQTT_CREDENTIALS {
        int id PK
        string device_id FK_UK
        string mqtt_username UK
        string mqtt_password_hash
        boolean enabled
        datetime created_at
        datetime updated_at
    }

    MQTT_ACL_RULES {
        int id PK
        string device_id FK
        string topic_pattern
        string permission
        datetime created_at
    }

    MQTT_SYNC_STATUS {
        int id PK
        int pending_changes
        datetime last_sync_at
        string last_sync_status
        datetime created_at
        datetime updated_at
    }

    LOCATION {
        int id PK
        float latitude
        float longitude
        datetime timestamp
        string username FK
        int user_id
        string display_time
        int battery
        float speed
        int chat_id
    }

Auto-Refresh Mechanismus

Die App verwendet einen Echtzeit-Ansatz:

  1. MQTT Subscriber empfängt OwnTracks Messages direkt vom Broker
  2. Locations werden sofort in SQLite gespeichert
  3. Frontend polling (alle 5 Sek.) → /api/locations
  4. API liest gefilterte Daten aus lokalem SQLite Cache
  5. Duplikate werden durch UNIQUE Index verhindert

Vorteile:

  • Echtzeitdaten ohne Verzögerung
  • Schnelle Antwortzeiten (direkter SQLite Zugriff)
  • Längere Zeiträume abrufbar (24h+)
  • Keine externen Dependencies
  • Duplikate werden automatisch verhindert (UNIQUE Index)

Datenvalidierung & Normalisierung

Die App behandelt spezielle Fälle bei speed/battery korrekt:

speed = 0 Behandlung:

  • MQTT sendet speed: 0 (gültig - Gerät steht still)
  • Wird mit typeof === 'number' Check explizit als 0 gespeichert
  • Wird NICHT zu null konvertiert (wichtig für Telemetrie)
  • Popup zeigt "Speed: 0.0 km/h" an

Debug-Logging:

  • Server-Logs zeigen MQTT Message-Verarbeitung
  • Browser Console zeigt Daten-Flow (MapView, Popup)
  • Hilfreich für Troubleshooting

📡 API-Endpunkte

Öffentlich

GET /api/locations

  • Location-Daten abrufen (aus SQLite Cache)
  • Query-Parameter:
    • username - Device-Filter (z.B. "10", "11")
    • Zeitfilter (wähle eine Methode):
      • timeRangeHours - Quick Filter (1, 3, 6, 12, 24)
      • startTime & endTime - Custom Range (ISO 8601 Format)
    • limit - Max. Anzahl (Standard: 1000)

Beispiele:

# Quick Filter: Letzte 3 Stunden
GET /api/locations?timeRangeHours=3

# Custom Range: Spezifischer Zeitraum
GET /api/locations?startTime=2025-11-16T16:00:00.000Z&endTime=2025-11-17T06:00:00.000Z

# Kombiniert: Device + Custom Range
GET /api/locations?username=10&startTime=2025-11-16T16:00:00.000Z&endTime=2025-11-17T06:00:00.000Z

GET /api/devices/public

  • Öffentliche Device-Liste (nur ID, Name, Color)

Geschützt (Login erforderlich)

GET /api/devices

  • Alle Geräte mit Latest Location und Telemetrie

POST /api/devices

  • Neues Gerät erstellen
  • Body: { id, name, color, description? }

PATCH /api/devices/:id

  • Gerät aktualisieren
  • Body: { name?, color?, description? }

DELETE /api/devices/:id

  • Gerät löschen (soft delete)

POST /api/locations/cleanup

  • Alte Locations löschen
  • Body: { retentionHours }

POST /api/locations/optimize

  • VACUUM + ANALYZE ausführen
  • Gibt freigegebenen Speicher zurück

GET /api/locations/stats

  • Detaillierte DB-Statistiken
  • Größe, Zeitraum, Locations pro Device

GET /api/system/status

  • System-Status abrufen
  • Returns: Uptime, Memory Usage, Node.js Version, Platform
  • Auto-Refresh: Alle 10 Sekunden im Admin-Panel

📱 Device Management

Device-Karte zeigt:

  • 🟢/ Online/Offline Status
    • Online = letzte Location < 10 Minuten
    • Offline = letzte Location > 10 Minuten
  • 🕒 Last Seen - Zeitstempel letzter Location
  • 🔋 Batterie - Prozent (Rot bei < 20%)
  • 🚗 Geschwindigkeit - km/h (umgerechnet von m/s)
  • 📍 Koordinaten - Lat/Lon mit 5 Dezimalen

Auto-Refresh

  • Devices-Seite aktualisiert sich alle 10 Sekunden
  • Online/Offline Status wird automatisch aktualisiert

🧹 Wartung

Datenbank aufräumen

Via Admin-Panel:

  • /admin → Database Maintenance → Cleanup Buttons

Via CLI:

npm run db:cleanup        # 7 Tage
npm run db:cleanup:30d    # 30 Tage

Datenbank optimieren

Via Admin-Panel:

  • /admin → Database Maintenance → Optimize Button

Via CLI:

# Manuell
node scripts/optimize-db.js

Was macht Optimize:

  • VACUUM - Speicherplatz freigeben
  • ANALYZE - Query-Statistiken aktualisieren

Logs prüfen

# Development Server Logs
npm run dev

# Production Logs (PM2)
pm2 logs location-tracker-app

Zeitfilter debuggen

Bei Problemen mit der Zeitfilterung (z.B. alte Locations werden nicht ausgefiltert):

node scripts/test-time-filter.js

Das Script zeigt:

  • Aktuelle Zeit (UTC und lokal)
  • Letzte Locations in der Datenbank
  • Welche Locations mit 1-Stunden-Filter angezeigt werden sollten
  • Vergleich zwischen alter (SQLite datetime) und neuer (JavaScript) Methode
  • Anzahl der gefilterten Locations

Verwendung:

  1. Script ausführen um zu sehen, welche Locations in der DB sind
  2. Überprüfen ob die Zeitfilterung korrekt funktioniert
  3. Bei Problemen: App neu starten nach Code-Updates

🚀 Deployment

Environment Variables

Erstelle .env.local:

# NextAuth
AUTH_SECRET=<generiere-mit-openssl-rand-base64-32>
NEXTAUTH_URL=https://your-domain.com

Secret generieren:

openssl rand -base64 32

Production Build

# Build
npm run build

# Start
npm run start

Mit PM2 (empfohlen)

# PM2 installieren
npm install -g pm2

# App starten
pm2 start npm --name "location-tracker-app" -- start

# Auto-Start bei Server-Neustart
pm2 startup
pm2 save

Nginx Reverse Proxy

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

🔒 Sicherheit

Production Checklist

  • AUTH_SECRET mit starkem Wert setzen
  • NEXTAUTH_URL auf Production-Domain setzen
  • Admin-Passwort ändern (nicht admin123)
  • Ggf. weitere User anlegen mit VIEWER Rolle
  • HTTPS aktivieren (Let's Encrypt)
  • Firewall-Regeln prüfen
  • Regelmäßige Backups einrichten

User-Rollen

  • ADMIN - Voller Zugriff auf alle Admin-Funktionen
  • VIEWER - Nur lesender Zugriff (geplant, noch nicht implementiert)

📂 Projektstruktur

location-tracker-app/
├── app/
│   ├── api/
│   │   ├── auth/[...nextauth]/      # NextAuth API
│   │   ├── devices/                 # Device CRUD
│   │   ├── locations/               # Location API + Sync/Cleanup/Stats
│   │   └── system/status/           # System Status (Uptime, Memory)
│   ├── admin/
│   │   ├── devices/                 # Device Management
│   │   └── page.tsx                 # Dashboard
│   ├── login/                       # Login-Seite
│   ├── page.tsx                     # Öffentliche Karte
│   └── layout.tsx                   # Root Layout
├── components/
│   └── map/
│       └── MapView.tsx              # Leaflet Map Component
├── lib/
│   ├── auth.ts                      # NextAuth Config
│   └── db.ts                        # SQLite Database Layer
├── scripts/
│   ├── init-database.js             # Database.sqlite Setup
│   ├── init-locations-db.js         # Locations.sqlite Setup
│   ├── reset-admin.js               # Admin User Reset
│   ├── remove-duplicates.js         # Duplikate bereinigen
│   └── cleanup-old-locations.js     # Alte Daten löschen
├── data/
│   ├── database.sqlite              # User + Devices
│   └── locations.sqlite             # Location Tracking
├── types/
│   └── location.ts                  # TypeScript Interfaces
└── middleware.ts                    # Route Protection

📝 Changelog

Version 1.1.0 - November 2025

🆕 Neue Features

  • Custom Date Range Filter
    • Benutzerdefinierte Zeiträume mit DateTime-Picker (z.B. 16.11.2025 16:00 - 17.11.2025 06:00)
    • Toggle-Button zwischen Quick Filters und Custom Range
    • Kompakte UI - Custom Range nur sichtbar wenn aktiviert
    • Backend-Support mit startTime und endTime API-Parametern

🐛 Bug Fixes

  • Zeitfilter-Bug behoben
    • Alte Locations (z.B. 6+ Stunden alt) werden jetzt korrekt ausgefiltert
    • JavaScript-basierte Zeitberechnung statt SQLite datetime('now')
    • Verhindert Zeitversatz-Probleme

🛠️ Verbesserungen

  • Zoom-basierte Icon-Skalierung für bessere Sichtbarkeit
  • Optimierte Zeitfilter-Logik in Datenbank-Queries
  • Debug-Script test-time-filter.js für Troubleshooting

📚 Dokumentation

  • README aktualisiert mit Custom Range Anleitung
  • API-Endpunkte Dokumentation erweitert
  • Wartungs-Abschnitt mit Debug-Script Information

🐛 Troubleshooting

"Invalid username or password"

Lösung:

node scripts/reset-admin.js

Datenbank-Dateien fehlen

Lösung:

npm run db:init

Duplikate in locations.sqlite

Lösung:

# Erst Duplikate entfernen
node scripts/remove-duplicates.js

# Dann UNIQUE Index hinzufügen
node scripts/init-locations-db.js

Map zeigt keine Daten

  1. MQTT Broker erreichbar? mosquitto_sub -h localhost -p 1883 -t '#'
  2. Locations in Datenbank? /admin → Database Statistics prüfen
  3. MQTT Subscriber läuft? Server-Logs prüfen

"ENOENT: no such file or directory, open 'data/database.sqlite'"

Lösung:

mkdir -p data
npm run db:init

📝 NPM Scripts

# Development
npm run dev              # Dev Server starten

# Production
npm run build            # Production Build
npm run start            # Production Server

# Database
npm run db:init          # Beide DBs initialisieren
npm run db:init:app      # Nur database.sqlite
npm run db:init:locations # Nur locations.sqlite
npm run db:cleanup       # Cleanup 7 Tage
npm run db:cleanup:7d    # Cleanup 7 Tage
npm run db:cleanup:30d   # Cleanup 30 Tage

# Linting
npm run lint             # ESLint ausführen

📄 Lizenz

MIT License - Open Source


📜 Open Source Lizenzen

Diese Anwendung verwendet folgende Open-Source-Software:

MIT License

Apache License 2.0

  • TypeScript - Copyright (c) Microsoft Corporation

ISC License

BSD-2-Clause License

  • Leaflet - Copyright (c) Vladimir Agafonkin

Hippocratic License 2.1

Vollständige Lizenztexte: Alle vollständigen Lizenztexte der verwendeten Bibliotheken finden Sie in den jeweiligen GitHub-Repositories oder in der node_modules Directory nach Installation.


🙏 Credits

  • Next.js 14 - React Framework
  • Leaflet.js - Karten-Bibliothek
  • NextAuth.js - Authentifizierung
  • better-sqlite3 - SQLite für Node.js
  • Tailwind CSS - Utility-First CSS
  • MQTT.js - MQTT Client für Node.js
  • OwnTracks - Location Tracking Apps

📞 Support

Bei Fragen oder Problemen:

  1. Logs prüfen (npm run dev Output)
  2. Browser Console öffnen (F12)
  3. Datenbank-Status in /admin prüfen
  4. Issues im Repository erstellen
Description
No description provided
Readme 1.6 MiB
Languages
TypeScript 87.1%
JavaScript 12%
Shell 0.6%
Dockerfile 0.2%