v2
This commit is contained in:
commit
787aab5e1d
16 changed files with 7129 additions and 0 deletions
7
.eslintrc.json
Normal file
7
.eslintrc.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"extends": "next/core-web-vitals",
|
||||||
|
"rules": {
|
||||||
|
"react-hooks/rules-of-hooks": "error",
|
||||||
|
"react-hooks/exhaustive-deps": "warn"
|
||||||
|
}
|
||||||
|
}
|
||||||
34
.gitignore
vendored
Normal file
34
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
.yarn/install-state.gz
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
117
README.md
Normal file
117
README.md
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
# Homelab Dashboard
|
||||||
|
|
||||||
|
Ein modernes, responsives Dashboard für die Verwaltung von Homelab-Diensten, gebaut mit **Next.js 15**, **TypeScript** und **Tailwind CSS**.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
✨ **Moderne Benutzeroberfläche**
|
||||||
|
- Elegantes Dark/Light Mode Design
|
||||||
|
- Responsive Grid-Layout für alle Bildschirmgrößen
|
||||||
|
- Smooth Animations und Übergänge
|
||||||
|
|
||||||
|
🎯 **Service-Management**
|
||||||
|
- Service-Karten mit Name, Beschreibung und Status
|
||||||
|
- Farbcodierter Status-Indikator (Online, Warnung, Offline)
|
||||||
|
- Direkte Links zu Services
|
||||||
|
- Pulsierender Status-Punkt für visuelle Rückmeldung
|
||||||
|
|
||||||
|
📱 **Mobile-First Design**
|
||||||
|
- Optimiert für Smartphones, Tablets und Desktop
|
||||||
|
- Touch-freundliche Buttons
|
||||||
|
- Flexibles Grid-System
|
||||||
|
|
||||||
|
## Installation & Setup
|
||||||
|
|
||||||
|
### Voraussetzungen
|
||||||
|
- Node.js 18+ installiert
|
||||||
|
- npm oder yarn
|
||||||
|
|
||||||
|
### Schritt 1: Dependencies installieren
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schritt 2: Entwicklungsserver starten
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Server läuft dann unter `http://localhost:3000`
|
||||||
|
|
||||||
|
## Projekt-Struktur
|
||||||
|
|
||||||
|
```
|
||||||
|
homelab-dashboard/
|
||||||
|
├── app/
|
||||||
|
│ ├── components/
|
||||||
|
│ │ ├── Header.tsx # Header-Komponente
|
||||||
|
│ │ └── ServiceCard.tsx # Service-Karten-Komponente
|
||||||
|
│ ├── globals.css # Globale Tailwind Styles
|
||||||
|
│ ├── layout.tsx # Root Layout
|
||||||
|
│ └── page.tsx # Startseite
|
||||||
|
├── lib/
|
||||||
|
│ └── data.ts # Mock-Daten und Service-Typen
|
||||||
|
├── tailwind.config.ts # Tailwind Konfiguration
|
||||||
|
├── postcss.config.js # PostCSS Konfiguration
|
||||||
|
├── next.config.js # Next.js Konfiguration
|
||||||
|
├── tsconfig.json # TypeScript Konfiguration
|
||||||
|
└── package.json # Abhängigkeiten
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dienste hinzufügen/bearbeiten
|
||||||
|
|
||||||
|
Bearbeite die Datei [src/data/services.ts](src/data/services.ts):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export const services: Service[] = [
|
||||||
|
{
|
||||||
|
id: 'unique-id',
|
||||||
|
name: 'Dein Service',
|
||||||
|
description: 'Was macht dieser Service?',
|
||||||
|
category: 'Infrastruktur', // oder Smart Home, Medien, Dokumente
|
||||||
|
status: 'online', // online | warning | offline
|
||||||
|
url: 'http://localhost:8000',
|
||||||
|
icon: '🖥️', // Optional - ein Emoji für visuelles Feedback
|
||||||
|
},
|
||||||
|
// ... weitere Services
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verfügbare Kategorien
|
||||||
|
|
||||||
|
- **Infrastruktur**: Server, Netzwerk, Monitoring
|
||||||
|
- **Smart Home**: Home Automation und IoT
|
||||||
|
- **Medien**: Medienserver und Downloading
|
||||||
|
- **Dokumente**: Dateispeicher und Code-Repositories
|
||||||
|
|
||||||
|
## Verfügbare Commands
|
||||||
|
|
||||||
|
- `npm run dev` - Entwicklungsserver starten
|
||||||
|
- `npm run build` - Produktions-Build erstellen
|
||||||
|
- `npm start` - Produktions-Server starten
|
||||||
|
- `npm run lint` - Linter ausführen
|
||||||
|
|
||||||
|
## Status-Indikatoren
|
||||||
|
|
||||||
|
| Status | Farbe | Beschreibung |
|
||||||
|
|--------|-------|-------------|
|
||||||
|
| Online | 🟢 Grün | Service läuft einwandfrei |
|
||||||
|
| Warning | 🟡 Orange | Service hat Probleme, läuft aber |
|
||||||
|
| Offline | 🔴 Rot | Service ist nicht erreichbar |
|
||||||
|
|
||||||
|
## Styling & Anpassungen
|
||||||
|
|
||||||
|
Das Projekt nutzt **Tailwind CSS** für Styling. Eigene Farben und Konfiguration können in [tailwind.config.ts](tailwind.config.ts) angepasst werden.
|
||||||
|
|
||||||
|
## Browser-Unterstützung
|
||||||
|
|
||||||
|
Das Dashboard funktioniert auf modernen Browsern:
|
||||||
|
- Chrome/Edge 90+
|
||||||
|
- Firefox 88+
|
||||||
|
- Safari 14+
|
||||||
|
|
||||||
|
## Lizenz
|
||||||
|
|
||||||
|
MIT
|
||||||
18
app/components/Header.tsx
Normal file
18
app/components/Header.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
export function Header() {
|
||||||
|
return (
|
||||||
|
<header className="bg-gradient-to-r from-slate-900 to-slate-800 border-b border-slate-700 shadow-lg">
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<h1 className="text-3xl sm:text-4xl font-bold text-white tracking-tight">
|
||||||
|
Homelab Dashboard
|
||||||
|
</h1>
|
||||||
|
<p className="text-slate-400 text-sm">
|
||||||
|
Übersicht aller verwalteten Dienste
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
97
app/components/ServiceCard.tsx
Normal file
97
app/components/ServiceCard.tsx
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Service } from '@/lib/data';
|
||||||
|
|
||||||
|
interface ServiceCardProps {
|
||||||
|
service: Service;
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusConfig = {
|
||||||
|
online: {
|
||||||
|
bgColor: 'bg-green-50 dark:bg-green-950',
|
||||||
|
textColor: 'text-green-700 dark:text-green-300',
|
||||||
|
dotColor: 'bg-green-500',
|
||||||
|
label: 'Online',
|
||||||
|
},
|
||||||
|
warning: {
|
||||||
|
bgColor: 'bg-amber-50 dark:bg-amber-950',
|
||||||
|
textColor: 'text-amber-700 dark:text-amber-300',
|
||||||
|
dotColor: 'bg-amber-500',
|
||||||
|
label: 'Warnung',
|
||||||
|
},
|
||||||
|
offline: {
|
||||||
|
bgColor: 'bg-red-50 dark:bg-red-950',
|
||||||
|
textColor: 'text-red-700 dark:text-red-300',
|
||||||
|
dotColor: 'bg-red-500',
|
||||||
|
label: 'Offline',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ServiceCard({ service }: ServiceCardProps) {
|
||||||
|
const config = statusConfig[service.status];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={service.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="group block"
|
||||||
|
>
|
||||||
|
<div className="h-full bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg shadow-sm hover:shadow-md transition-all duration-300 overflow-hidden hover:border-slate-300 dark:hover:border-slate-600">
|
||||||
|
<div className="p-6 flex flex-col gap-4 h-full">
|
||||||
|
{/* Header mit Name und Status */}
|
||||||
|
<div className="flex items-start justify-between gap-4">
|
||||||
|
<div className="flex-1 flex items-center gap-3">
|
||||||
|
{service.icon && <span className="text-2xl">{service.icon}</span>}
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold text-slate-900 dark:text-white group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
|
||||||
|
{service.name}
|
||||||
|
</h3>
|
||||||
|
<p className="text-xs text-slate-500 dark:text-slate-400">
|
||||||
|
{service.category}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={`flex items-center gap-2 px-3 py-1 rounded-full ${config.bgColor}`}>
|
||||||
|
<span className={`w-2 h-2 rounded-full ${config.dotColor} animate-pulse`} />
|
||||||
|
<span className={`text-xs font-medium ${config.textColor}`}>
|
||||||
|
{config.label}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Beschreibung */}
|
||||||
|
<p className="text-sm text-slate-600 dark:text-slate-400 flex-grow">
|
||||||
|
{service.description}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Button */}
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
window.open(service.url, '_blank');
|
||||||
|
}}
|
||||||
|
className="w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition-colors duration-200 flex items-center justify-center gap-2 group/btn"
|
||||||
|
>
|
||||||
|
Öffnen
|
||||||
|
<svg
|
||||||
|
className="w-4 h-4 group-hover/btn:translate-x-1 transition-transform"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
21
app/globals.css
Normal file
21
app/globals.css
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
* {
|
||||||
|
@apply border-slate-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
color-scheme: light dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
@apply bg-slate-50 dark:bg-slate-900 text-slate-900 dark:text-slate-50;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer components {
|
||||||
|
.card {
|
||||||
|
@apply bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
app/layout.tsx
Normal file
20
app/layout.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
import { Metadata as NextMetadata } from 'next';
|
||||||
|
|
||||||
|
export const metadata: NextMetadata = {
|
||||||
|
manifest: '/manifest.json',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<html lang="de">
|
||||||
|
<body className="antialiased">
|
||||||
|
{children}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
52
app/page.tsx
Normal file
52
app/page.tsx
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
import { Header } from './components/Header';
|
||||||
|
import { ServiceCard } from './components/ServiceCard';
|
||||||
|
import { services } from '@/lib/data';
|
||||||
|
import './globals.css';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Homelab Dashboard',
|
||||||
|
description: 'Verwaltungs-Dashboard für dein Homelab',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-slate-50 dark:bg-slate-900">
|
||||||
|
<Header />
|
||||||
|
|
||||||
|
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||||
|
{/* Services Grid */}
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
||||||
|
{services.map((service) => (
|
||||||
|
<ServiceCard key={service.id} service={service} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Empty State (falls keine Services) */}
|
||||||
|
{services.length === 0 && (
|
||||||
|
<div className="flex flex-col items-center justify-center py-12">
|
||||||
|
<svg
|
||||||
|
className="w-16 h-16 text-slate-400 mb-4"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<h3 className="text-xl font-semibold text-slate-900 dark:text-white">
|
||||||
|
Keine Dienste konfiguriert
|
||||||
|
</h3>
|
||||||
|
<p className="text-slate-600 dark:text-slate-400 mt-2">
|
||||||
|
Füge Dienste in der Datenkonfiguration hinzu, um sie hier anzuzeigen
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
2
lib/data.ts
Normal file
2
lib/data.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
// Re-export from the main services data file
|
||||||
|
export * from '@/src/data/services';
|
||||||
4
next.config.js
Normal file
4
next.config.js
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {}
|
||||||
|
|
||||||
|
module.exports = nextConfig
|
||||||
6521
package-lock.json
generated
Normal file
6521
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
29
package.json
Normal file
29
package.json
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"name": "homelab-dashboard",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "^16.2.3",
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^20.10.6",
|
||||||
|
"@types/react": "^18.2.46",
|
||||||
|
"@types/react-dom": "^18.2.18",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.58.2",
|
||||||
|
"@typescript-eslint/parser": "^8.58.2",
|
||||||
|
"autoprefixer": "^10.4.16",
|
||||||
|
"eslint": "^8.56.0",
|
||||||
|
"eslint-config-next": "^15.0.3",
|
||||||
|
"postcss": "^8.4.32",
|
||||||
|
"tailwindcss": "^3.4.1",
|
||||||
|
"typescript": "^5.3.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
10
postcss.config.js
Normal file
10
postcss.config.js
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import type { Config } from 'postcss-load-config'
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default config
|
||||||
130
src/data/services.ts
Normal file
130
src/data/services.ts
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
export type ServiceCategory = 'Infrastruktur' | 'Smart Home' | 'Medien' | 'Dokumente';
|
||||||
|
export type ServiceStatus = 'online' | 'warning' | 'offline';
|
||||||
|
|
||||||
|
export interface Service {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
category: ServiceCategory;
|
||||||
|
status: ServiceStatus;
|
||||||
|
url: string;
|
||||||
|
icon?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const services: Service[] = [
|
||||||
|
// Infrastruktur
|
||||||
|
{
|
||||||
|
id: 'unraid',
|
||||||
|
name: 'Unraid',
|
||||||
|
description: 'NAS und Server Management Platform',
|
||||||
|
category: 'Infrastruktur',
|
||||||
|
status: 'online',
|
||||||
|
url: 'http://localhost',
|
||||||
|
icon: '🖥️',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'unifi',
|
||||||
|
name: 'UniFi',
|
||||||
|
description: 'Netzwerk-Management und WLAN-Controller',
|
||||||
|
category: 'Infrastruktur',
|
||||||
|
status: 'online',
|
||||||
|
url: 'http://localhost:8443',
|
||||||
|
icon: '🌐',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'checkmk',
|
||||||
|
name: 'Checkmk',
|
||||||
|
description: 'Monitoring und Alerting System',
|
||||||
|
category: 'Infrastruktur',
|
||||||
|
status: 'online',
|
||||||
|
url: 'http://localhost/checkmk',
|
||||||
|
icon: '📊',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'nginx-proxy',
|
||||||
|
name: 'Nginx Proxy Manager',
|
||||||
|
description: 'Reverse Proxy und SSL-Verwaltung',
|
||||||
|
category: 'Infrastruktur',
|
||||||
|
status: 'online',
|
||||||
|
url: 'http://localhost:81',
|
||||||
|
icon: '⚙️',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Smart Home
|
||||||
|
{
|
||||||
|
id: 'home-assistant',
|
||||||
|
name: 'Home Assistant',
|
||||||
|
description: 'Smart Home Automation und Integration',
|
||||||
|
category: 'Smart Home',
|
||||||
|
status: 'offline',
|
||||||
|
url: 'http://localhost:8123',
|
||||||
|
icon: '🏠',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Medien
|
||||||
|
{
|
||||||
|
id: 'plex',
|
||||||
|
name: 'Plex',
|
||||||
|
description: 'Medienserver und Streaming-Dienst',
|
||||||
|
category: 'Medien',
|
||||||
|
status: 'online',
|
||||||
|
url: 'http://localhost:32400',
|
||||||
|
icon: '🎬',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'jellyfin',
|
||||||
|
name: 'Jellyfin',
|
||||||
|
description: 'Open-Source Medienserver',
|
||||||
|
category: 'Medien',
|
||||||
|
status: 'online',
|
||||||
|
url: 'http://localhost:8096',
|
||||||
|
icon: '📺',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'radarr',
|
||||||
|
name: 'Radarr',
|
||||||
|
description: 'Automatisches Filmmanagement',
|
||||||
|
category: 'Medien',
|
||||||
|
status: 'online',
|
||||||
|
url: 'http://localhost:7878',
|
||||||
|
icon: '🎥',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sonarr',
|
||||||
|
name: 'Sonarr',
|
||||||
|
description: 'Automatisches Serienmanagement',
|
||||||
|
category: 'Medien',
|
||||||
|
status: 'online',
|
||||||
|
url: 'http://localhost:8989',
|
||||||
|
icon: '📺',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'prowlarr',
|
||||||
|
name: 'Prowlarr',
|
||||||
|
description: 'Indexer und Proxy Manager',
|
||||||
|
category: 'Medien',
|
||||||
|
status: 'warning',
|
||||||
|
url: 'http://localhost:9696',
|
||||||
|
icon: '🔍',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Dokumente
|
||||||
|
{
|
||||||
|
id: 'seafile',
|
||||||
|
name: 'Seafile',
|
||||||
|
description: 'Dateifreigabe und Cloud Storage',
|
||||||
|
category: 'Dokumente',
|
||||||
|
status: 'online',
|
||||||
|
url: 'http://localhost:8000',
|
||||||
|
icon: '☁️',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'forgejo',
|
||||||
|
name: 'Forgejo',
|
||||||
|
description: 'Self-hosted Git und Code Repository',
|
||||||
|
category: 'Dokumente',
|
||||||
|
status: 'online',
|
||||||
|
url: 'http://localhost:3000',
|
||||||
|
icon: '💾',
|
||||||
|
},
|
||||||
|
];
|
||||||
18
tailwind.config.ts
Normal file
18
tailwind.config.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import type { Config } from 'tailwindcss'
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
content: [
|
||||||
|
'./app/**/*.{js,ts,jsx,tsx,mdx}',
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
success: '#10b981',
|
||||||
|
warning: '#f59e0b',
|
||||||
|
error: '#ef4444',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
|
export default config
|
||||||
49
tsconfig.json
Normal file
49
tsconfig.json
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": [
|
||||||
|
"ES2020",
|
||||||
|
"DOM",
|
||||||
|
"DOM.Iterable"
|
||||||
|
],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"./*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"allowJs": true,
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".next/types/**/*.ts",
|
||||||
|
".next/dev/types/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue