Eine moderne, offline-fähige Progressive Web App zum Tracken von Filmen, Visualisieren von Watchlisten und KI-gestützten Empfehlungen
Features • Demo • Installation • Dokumentation • Contributing
- Übersicht
- Features
- Tech Stack
- Architektur
- Voraussetzungen
- Installation
- Konfiguration
- Entwicklung
- Deployment
- PWA & Mobile
- Projektstruktur
- API-Referenz
- Testing
- Performance
- Troubleshooting
- Contributing
- Roadmap
- License
InFocus CineLog ist eine moderne Progressive Web App, die entwickelt wurde, um die Lücke zwischen Web-Anwendungen und nativen mobilen Erlebnissen zu schließen. Die App ermöglicht es Nutzern, ihre Filme zu tracken, Watchlisten zu verwalten, detaillierte Statistiken über ihre Sehgewohnheiten zu visualisieren und KI-gestützte Filmempfehlungen zu erhalten.
- 📱 Mobile-First: Optimiert für mobile Endgeräte mit nativem Look & Feel
- ⚡ Offline-First: Volle Funktionalität auch ohne Internetverbindung
- 🎨 Modern Design: Glassmorphism UI mit flüssigen Animationen
- 🔐 Secure: Supabase Auth mit Row Level Security (RLS)
- 📊 Data-Driven: Umfassende Statistiken und Visualisierungen
- Erweiterte Suche: Integration mit der TMDB API für Zugriff auf Millionen von Filmen
- Watch Status: Markiere Filme als "Gesehen", "Watchlist" oder "Favoriten"
- Detaillierte Filminfos: Cast, Crew, Trailer, Budget, Einspielergebnis, etc.
- Bewertungssystem: Eigene Bewertungen (1-10) und Notizen hinzufügen
- Cover & Poster: Hochauflösende Filmcover automatisch von TMDB
- Watchtime-Tracker: Gesamte Sehdauer in Stunden/Tagen
- Genre-Analyse: Prozentuale Verteilung deiner Lieblingsgenres
- Jahres-Übersicht: Filme nach Erscheinungsjahr gruppiert
- Durchschnittsbewertungen: Deine durchschnittliche Bewertung pro Genre
- Watching Streaks: Längste Serien-Marathon-Sessions
- Top-Listen: Deine am besten bewerteten Filme, Directors, Actors
- Smart Recommendations: Personalisierte Filmempfehlungen basierend auf deinem Profil
- Genre-Matching: Algorithmus zur Analyse deiner Präferenzen
- Mood-Based Discovery: Finde Filme basierend auf deiner aktuellen Stimmung
- Similar Movies: "Wenn dir X gefällt, schau Y"-Vorschläge
- Installierbar: Als App auf dem Homescreen installieren
- Offline-Modus: Funktioniert vollständig offline nach erstem Laden
- Push-Benachrichtigungen: Erinnerungen für Watchlist-Filme (geplant)
- Background Sync: Automatische Datensynchronisation im Hintergrund
- Native Transitions: Smooth Page-Transitions wie in nativen Apps
- Supabase Auth: E-Mail/Passwort oder Magic Link Login
- Row Level Security: Jeder Nutzer sieht nur seine eigenen Daten
- Session Management: Sichere Token-basierte Sessions
- Password Reset: Passwort-Wiederherstellung via E-Mail
| Technologie | Version | Verwendung |
|---|---|---|
| React | 19.x | UI-Framework mit Hooks & Concurrent Features |
| TypeScript | 5.0+ | Typsicherheit für das gesamte Projekt |
| Vite | 5.x | Blitzschneller Build-Tool & Dev-Server |
| Tailwind CSS | 3.x | Utility-First CSS-Framework |
| Lucide React | Latest | Icon-Library (700+ Icons) |
| Technologie | Verwendung |
|---|---|
| Supabase | PostgreSQL Database, Auth, Realtime Subscriptions |
| TMDB API | Film-Metadaten, Poster, Trailer, Cast-Infos |
| Vercel/Netlify | Hosting & Deployment (empfohlen) |
| Technologie | Verwendung |
|---|---|
| Vite PWA Plugin | Service Worker, Manifest, Offline-Caching |
| Capacitor | Native Android/iOS Build (optional) |
| Workbox | Advanced Caching-Strategien |
| Tool | Verwendung |
|---|---|
| ESLint | Code-Quality & Linting |
| Prettier | Code-Formatting |
| Vitest | Unit & Integration Testing |
| Playwright | E2E-Testing |
| Husky | Git Hooks für Pre-Commit Checks |
InFocus CineLog folgt einer Clean Architecture mit klarer Trennung von Verantwortlichkeiten:
┌─────────────────────────────────────────────────────────┐
│ UI Layer (React) │
│ Components, Pages, Hooks, Routing │
└───────────────────┬─────────────────────────────────────┘
│
┌───────────────────▼─────────────────────────────────────┐
│ Conductor (State Management) │
│ Business Logic, State Orchestration │
└───────────────────┬─────────────────────────────────────┘
│
┌───────────────────▼─────────────────────────────────────┐
│ Service Layer │
│ AuthService, MovieService, TMDBService │
└───────────────────┬─────────────────────────────────────┘
│
┌───────────────────▼─────────────────────────────────────┐
│ External APIs & Database │
│ Supabase (PostgreSQL), TMDB API │
└─────────────────────────────────────────────────────────┘
Das Conductor Pattern ist das Herzstück der App-Architektur:
// Conductor orchestriert den gesamten App-State
class Conductor {
private authService: AuthService
private movieService: MovieService
// Zentrale State-Management-Methoden
async initialize(): Promise<void>
async login(email: string, password: string): Promise<void>
async addMovie(movie: Movie): Promise<void>
async updateWatchStatus(id: string, status: WatchStatus): Promise<void>
// Observable State für React-Integration
getState$(): Observable<AppState>
}✅ Klare Verantwortlichkeiten: UI-Komponenten sind "dumm", Business-Logic im Conductor
✅ Testbarkeit: Conductor kann isoliert ohne UI getestet werden
✅ Kein Prop-Drilling: Zentraler State via Context/Provider
✅ Wiederverwendbarkeit: Services können in anderen Projekten genutzt werden
Problem in Version <2.4:
// ❌ Mehrere Instanzen führten zu Auth-Sync-Problemen
const supabase1 = createClient(url, key) // in AuthService
const supabase2 = createClient(url, key) // in MovieServiceLösung ab Version 2.4+:
// ✅ Eine zentrale Singleton-Instanz
// src/lib/supabase.ts
export const supabase = createClient(
import.meta.env.VITE_SUPABASE_URL,
import.meta.env.VITE_SUPABASE_ANON_KEY
)
// Überall im Projekt verwenden
import { supabase } from '@/lib/supabase'✅ Keine "Multiple GoTrueClient"-Warnungen mehr
✅ Konsistenter Auth-State über die gesamte App
✅ Reduzierter Connection-Overhead
✅ Einfachere Konfiguration an einer zentralen Stelle
// AuthService: Zuständig für Authentication
class AuthService {
async login(email: string, password: string): Promise<User>
async logout(): Promise<void>
async getSession(): Promise<Session | null>
onAuthStateChange(callback: (user: User | null) => void): Unsubscribe
}
// MovieService: Zuständig für Movie-Operationen
class SupabaseMovieService implements MovieService {
async getMovies(userId: string): Promise<Movie[]>
async addMovie(movie: Movie): Promise<Movie>
async updateMovie(id: string, updates: Partial<Movie>): Promise<Movie>
async deleteMovie(id: string): Promise<void>
async searchTMDB(query: string): Promise<TMDBMovie[]>
}Stelle sicher, dass folgende Software installiert ist:
- Node.js: Version 18.x oder höher (Download)
- npm: Version 9.x oder höher (kommt mit Node.js)
- Git: Für Versionskontrolle (Download)
- Supabase Account: Kostenloser Account unter supabase.com
- TMDB API Key: Kostenloser Key unter themoviedb.org
node --version # sollte v18.0.0 oder höher sein
npm --version # sollte 9.0.0 oder höher sein
git --version # beliebige Versiongit clone https://github.com/IhrUsername/infocusmovieapp.git
cd infocusmovieappnpm installDies installiert alle benötigten Pakete aus der package.json.
- Gehe zu supabase.com und erstelle ein neues Projekt
- Wähle eine Region (z.B.
eu-central-1für Europa) - Setze ein sicheres Datenbank-Passwort
Führe folgendes SQL-Script in deinem Supabase SQL-Editor aus:
-- Movies Table
CREATE TABLE movies (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
tmdb_id INTEGER,
title TEXT NOT NULL,
original_title TEXT,
overview TEXT,
poster_path TEXT,
backdrop_path TEXT,
release_date DATE,
runtime INTEGER,
genres JSONB,
vote_average DECIMAL(3,1),
popularity DECIMAL(10,3),
-- User-spezifische Felder
watch_status TEXT CHECK (watch_status IN ('watched', 'watchlist', 'favorite')),
user_rating INTEGER CHECK (user_rating >= 1 AND user_rating <= 10),
notes TEXT,
watched_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Indexes für Performance
CREATE INDEX idx_movies_user_id ON movies(user_id);
CREATE INDEX idx_movies_tmdb_id ON movies(tmdb_id);
CREATE INDEX idx_movies_watch_status ON movies(watch_status);
-- Row Level Security aktivieren
ALTER TABLE movies ENABLE ROW LEVEL SECURITY;
-- Policy: User kann nur eigene Movies sehen
CREATE POLICY "Users can view own movies"
ON movies FOR SELECT
USING (auth.uid() = user_id);
-- Policy: User kann eigene Movies erstellen
CREATE POLICY "Users can create own movies"
ON movies FOR INSERT
WITH CHECK (auth.uid() = user_id);
-- Policy: User kann eigene Movies updaten
CREATE POLICY "Users can update own movies"
ON movies FOR UPDATE
USING (auth.uid() = user_id);
-- Policy: User kann eigene Movies löschen
CREATE POLICY "Users can delete own movies"
ON movies FOR DELETE
USING (auth.uid() = user_id);
-- Updated_at Trigger
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_movies_updated_at
BEFORE UPDATE ON movies
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();- Erstelle einen Account auf themoviedb.org
- Gehe zu Settings → API
- Beantrage einen API Key (kostenlos)
- Kopiere den API Key (v3 auth)
Erstelle eine .env-Datei im Root-Verzeichnis:
# Supabase Configuration
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key-here
# TMDB API
VITE_TMDB_API_KEY=your-tmdb-api-key-here
# Optional: Environment
VITE_ENV=development- Gehe zu deinem Supabase-Projekt
- Klicke auf Settings → API
- Kopiere:
- Project URL →
VITE_SUPABASE_URL - anon/public key →
VITE_SUPABASE_ANON_KEY
- Project URL →
.env-Datei steht in .gitignore und sollte NIEMALS committed werden!
Erstelle eine .env.example als Template:
# Copy this file to .env and fill in your actual values
VITE_SUPABASE_URL=https://xxxxx.supabase.co
VITE_SUPABASE_ANON_KEY=eyJxxx...
VITE_TMDB_API_KEY=xxxxxnpm run devDie App läuft nun unter: http://localhost:5173
| Command | Beschreibung |
|---|---|
npm run dev |
Startet Vite Dev-Server mit Hot-Reload |
npm run build |
Production Build erstellen |
npm run preview |
Production Build lokal testen |
npm run lint |
ESLint ausführen |
npm run lint:fix |
ESLint mit Auto-Fix |
npm run format |
Prettier Code-Formatting |
npm run type-check |
TypeScript Type-Checking |
npm run test |
Vitest Unit-Tests ausführen |
npm run test:e2e |
Playwright E2E-Tests |
Vite unterstützt HMR out-of-the-box. Änderungen werden sofort im Browser reflektiert ohne Full-Reload.
Die tsconfig.json ist optimiert für React 19:
{
"compilerOptions": {
"target": "ES2020",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"jsx": "react-jsx",
"strict": true,
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"paths": {
"@/*": ["./src/*"]
}
}
}Die tailwind.config.js enthält Custom-Extensions für Glassmorphism:
module.exports = {
theme: {
extend: {
colors: {
primary: '#6366f1',
secondary: '#8b5cf6',
},
backdropBlur: {
xs: '2px',
},
backgroundImage: {
'glass': 'linear-gradient(135deg, rgba(255,255,255,0.1), rgba(255,255,255,0))',
}
}
}
}-
Vercel CLI installieren:
npm install -g vercel
-
Projekt deployen:
vercel
-
Environment Variables setzen:
- Gehe zu Vercel Dashboard → Settings → Environment Variables
- Füge alle
.env-Variablen hinzu
-
Production Deployment:
vercel --prod
-
Netlify CLI installieren:
npm install -g netlify-cli
-
Build und Deploy:
npm run build netlify deploy --prod --dir=dist
-
Environment Variables in Netlify Dashboard unter Site Settings → Environment Variables setzen
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]Build und Run:
docker build -t infocus-cinelog .
docker run -p 80:80 infocus-cinelogDie App kann auf jedem Gerät als PWA installiert werden:
Desktop (Chrome/Edge):
- Klicke auf das ⊕ Install-Icon in der Adressleiste
- Oder: Menü → App installieren
Mobile (Android/iOS):
- Öffne die App im Browser
- Android: Tippe auf Menü → Zum Startbildschirm hinzufügen
- iOS: Tippe auf Teilen → Zum Home-Bildschirm
Der Service Worker cached automatisch:
- App Shell: HTML, CSS, JS
- Bilder: Poster, Backdrops (Cache-First-Strategie)
- API-Responses: TMDB-Daten (Network-First mit Fallback)
Die App funktioniert vollständig offline:
- ✅ Alle gespeicherten Filme sind verfügbar
- ✅ Statistiken werden lokal berechnet
- ✅ Neue Filme können hinzugefügt werden (Background Sync)
- ❌ TMDB-Suche erfordert Internet (wird als Fallback deaktiviert)
-
Capacitor installieren:
npm install @capacitor/core @capacitor/cli npm install @capacitor/android @capacitor/ios
-
Capacitor initialisieren:
npx cap init
-
Android Build:
npm run build npx cap add android npx cap sync npx cap open android
-
iOS Build (nur auf macOS):
npm run build npx cap add ios npx cap sync npx cap open ios
infocusmovieapp/
├── public/ # Statische Assets
│ ├── pwa-icon-512.png # PWA Icon (512x512)
│ ├── pwa-icon-192.png # PWA Icon (192x192)
│ ├── manifest.json # PWA Manifest
│ └── robots.txt
│
├── src/
│ ├── core/ # 🧠 Kern der Anwendung
│ │ ├── conductor/
│ │ │ ├── Conductor.ts # Zentrale State-Management-Logik
│ │ │ ├── ConductorContext.tsx # React Context Provider
│ │ │ └── useConductor.ts # React Hook
│ │ └── config/
│ │ └── constants.ts # App-weite Konstanten
│ │
│ ├── services/ # 🔌 API-Adapter & Business Logic
│ │ ├── AuthService.ts # Supabase Authentication
│ │ ├── MovieService.ts # Interface Definition
│ │ ├── SupabaseMovieService.ts # Supabase Implementation
│ │ └── TMDBService.ts # TMDB API Integration
│ │
│ ├── lib/ # 🛠️ Infrastructure & Utilities
│ │ ├── supabase.ts # ✨ Singleton Supabase Client
│ │ └── utils.ts # Helper-Funktionen
│ │
│ ├── types/ # 📝 TypeScript Definitionen
│ │ ├── domain.ts # Domain Models (Movie, User, etc.)
│ │ ├── auth.ts # Auth-bezogene Types
│ │ └── supabase.ts # Supabase-spezifische Types
│ │
│ ├── components/ # 🎨 React Components
│ │ ├── ui/ # Wiederverwendbare UI-Komponenten
│ │ │ ├── Button.tsx
│ │ │ ├── Card.tsx
│ │ │ ├── Input.tsx
│ │ │ └── Modal.tsx
│ │ ├── features/ # Feature-spezifische Komponenten
│ │ │ ├── MovieCard.tsx
│ │ │ ├── MovieList.tsx
│ │ │ ├── SearchBar.tsx
│ │ │ └── StatisticsChart.tsx
│ │ └── layout/ # Layout-Komponenten
│ │ ├── Header.tsx
│ │ ├── Navigation.tsx
│ │ └── Footer.tsx
│ │
│ ├── pages/ # 📄 Seiten/Views
│ │ ├── Home.tsx
│ │ ├── Login.tsx
│ │ ├── Movies.tsx
│ │ ├── Statistics.tsx
│ │ └── Profile.tsx
│ │
│ ├── hooks/ # 🪝 Custom React Hooks
│ │ ├── useAuth.ts
│ │ ├── useMovies.ts
│ │ └── useDebounce.ts
│ │
│ ├── styles/ # 🎨 Global Styles
│ │ └── globals.css
│ │
│ ├── App.tsx # Main App Component
│ ├── main.tsx # Entry Point
│ └── vite-env.d.ts # Vite Type Definitions
│
├── .env # Environment Variables (nicht committen!)
├── .env.example # Environment Template
├── .gitignore
├── package.json
├── tsconfig.json # TypeScript Config
├── tailwind.config.js # Tailwind Config
├── vite.config.ts # Vite Config
├── postcss.config.js # PostCSS Config
└── README.md
/core: Enthält die Business-Logic. Hier sollte KEIN React-Code sein (außer Context/Provider)/services: Reine Data-Access-Layer. Keine UI-Logik/components: Nur Präsentations-Komponenten. Business-Logic via Props/Hooks/pages: Container-Komponenten die Services/Conductor nutzen/hooks: Custom Hooks für wiederverwendbare Logik
class AuthService {
/**
* Login mit E-Mail und Passwort
*/
async login(email: string, password: string): Promise<{
user: User
session: Session
}>
/**
* Registrierung eines neuen Users
*/
async signUp(email: string, password: string): Promise<{
user: User
session: Session
}>
/**
* Logout
*/
async logout(): Promise<void>
/**
* Aktuelle Session abrufen
*/
async getSession(): Promise<Session | null>
/**
* Auth-State-Änderungen abonnieren
*/
onAuthStateChange(callback: (user: User | null) => void): () => void
}interface MovieService {
/**
* Alle Filme eines Users laden
*/
getMovies(userId: string): Promise<Movie[]>
/**
* Einzelnen Film abrufen
*/
getMovie(id: string): Promise<Movie | null>
/**
* Neuen Film hinzufügen
*/
addMovie(movie: Omit<Movie, 'id' | 'created_at'>): Promise<Movie>
/**
* Film aktualisieren
*/
updateMovie(id: string, updates: Partial<Movie>): Promise<Movie>
/**
* Film löschen
*/
deleteMovie(id: string): Promise<void>
/**
* TMDB durchsuchen
*/
searchTMDB(query: string): Promise<TMDBMovie[]>
/**
* Film-Details von TMDB
*/
getTMDBDetails(tmdbId: number): Promise<TMDBMovieDetails>
}class Conductor {
/**
* App initialisieren (Auth-Check, etc.)
*/
async initialize(): Promise<void>
/**
* Login
*/
async login(email: string, password: string): Promise<void>
/**
* Film zur Collection hinzufügen
*/
async addMovie(tmdbId: number, watchStatus: WatchStatus): Promise<void>
/**
* Watch-Status ändern
*/
async updateWatchStatus(movieId: string, status: WatchStatus): Promise<void>
/**
* Film bewerten
*/
async rateMovie(movieId: string, rating: number): Promise<void>
/**
* Statistiken abrufen
*/
getStatistics(): Statistics
/**
* App-State als Observable
*/
getState$(): Observable<AppState>
}# Alle Tests ausführen
npm run test
# Watch-Mode
npm run test:watch
# Coverage-Report
npm run test:coverageBeispiel-Test:
import { describe, it, expect } from 'vitest'
import { Conductor } from '@/core/conductor/Conductor'
describe('Conductor', () => {
it('should calculate correct statistics', () => {
const conductor = new Conductor()
// Test-Logic
})
})# E2E Tests ausführen
npm run test:e2e
# UI-Mode
npm run test:e2e:uiBeispiel E2E-Test:
import { test, expect } from '@playwright/test'
test('user can add movie to watchlist', async ({ page }) => {
await page.goto('http://localhost:5173')
await page.click('[data-testid="search-button"]')
await page.fill('[data-testid="search-input"]', 'Inception')
await page.click('[data-testid="add-to-watchlist"]')
await expect(page.locator('[data-testid="watchlist-count"]')).toHaveText('1')
})- Performance: 95+
- Accessibility: 100
- Best Practices: 95+
- SEO: 100
- PWA: ✓
- ✅ Code-Splitting: Automatisch via Vite/React.lazy
- ✅ Image Optimization: TMDB-Bilder werden lazy-loaded
- ✅ Tree-Shaking: Ungenutzter Code wird entfernt
- ✅ Minification: CSS/JS wird minifiziert
- ✅ Caching: Aggressive Service-Worker-Strategien
- ✅ Preload: Kritische Resources werden preloaded
# Bundle-Größe analysieren
npm run build
npx vite-bundle-visualizerZiel: < 200 KB (gzipped) für Initial-Bundle
Lösung: Stelle sicher, dass du Version 2.4+ verwendest und überall den Singleton-Client importierst:
// ✅ Richtig
import { supabase } from '@/lib/supabase'
// ❌ Falsch
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(url, key)Mögliche Ursachen:
- CORS-Problem: TMDB erlaubt Cross-Origin. Prüfe Console auf Fehler
- Falscher Image-Path: TMDB-Paths sind relativ. Stelle sicher, dass du
https://image.tmdb.org/t/p/original/uxzzxijgPIY7slzFvMotPv8wjKA.jpgvoranstellst
// ✅ Richtig
const posterUrl = `https://image.tmdb.org/t/p/original/rzRb63TldOKdKydCvWJM8B6EkPM.jpg`
// ❌ Falsch
const posterUrl = movie.poster_pathLösung:
- Prüfe ob Service Worker registriert ist: DevTools → Application → Service Workers
- Checke Caching-Strategien in
vite.config.ts - Stelle sicher, dass die App mindestens einmal online geladen wurde
Lösung: Überprüfe deine RLS-Policies:
-- Debug: Temporär RLS deaktivieren (NUR FÜR TESTS!)
ALTER TABLE movies DISABLE ROW LEVEL SECURITY;
-- Prüfe ob User eingeloggt ist
SELECT auth.uid(); -- sollte eine UUID zurückgebenHäufige Ursachen:
- TypeScript-Fehler:
npm run type-check - Fehlende Env-Vars: Prüfe ob
.envalle Variablen enthält - Dependency-Konflikte:
rm -rf node_modules && npm install
Beiträge sind willkommen! Bitte folge diesen Guidelines:
git clone https://github.com/YourUsername/infocusmovieapp.git
cd infocusmovieapp
git remote add upstream https://github.com/OriginalOwner/infocusmovieapp.gitgit checkout -b feature/amazing-new-featureBranch-Naming-Convention:
feature/- Neue Featuresfix/- Bugfixesdocs/- Dokumentationrefactor/- Code-Refactoring
# Code schreiben
npm run dev
# Tests ausführen
npm run test
npm run lint
# Build testen
npm run build
npm run previewWir verwenden Conventional Commits:
git commit -m "feat: add genre filter to movie list"
git commit -m "fix: resolve login redirect loop"
git commit -m "docs: update installation guide"- Push zu deinem Fork:
git push origin feature/amazing-new-feature - Öffne einen Pull Request auf GitHub
- Beschreibe deine Änderungen detailliert
- Warte auf Review
- ESLint: Wird automatisch via Pre-Commit-Hook geprüft
- Prettier: Formatierung erfolgt automatisch
- TypeScript: Strict-Mode ist aktiviert, keine
any-Types
- Social Features: Filme mit Freunden teilen
- Watchlist-Gruppen: Gemeinsame Watchlists
- Advanced Recommendations: ML-basierte Empfehlungen
- Streaming-Integration: Zeige wo Filme verfügbar sind
- Dark/Light Mode: Theme-Switcher
- Export-Feature: Daten als CSV/JSON exportieren
- Import von Letterboxd/IMDb: Migration von anderen Plattformen
- Push-Benachrichtigungen: Erinnerungen für Watchlist
- Trailer-Integration: YouTube-Trailer direkt in der App
- Desktop-App: Electron-Wrapper für native Desktop-Experience
- Browser-Extension: Chrome/Firefox-Extension
- API für Drittanbieter: Public API für Entwickler
- Multi-Language: i18n-Support (DE, EN, FR, ES)
MIT License
Copyright (c) 2026 InFocus CineLog
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Supabase: Für die fantastische BaaS-Plattform
- TMDB: Für die umfassende Film-API
- Vite: Für den blitzschnellen Build-Tool
- React Team: Für React 19 und die neuen Concurrent Features
- Tailwind Labs: Für das großartige CSS-Framework
- GitHub Issues: Issues
- Discussions: GitHub Discussions
- Email: support@infocuscinelog.app
- Twitter: @InFocusCineLog
Entwickelt mit ❤️ und ☕