256 lines
10 KiB
TypeScript
256 lines
10 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
|
|
interface App {
|
|
name: string;
|
|
icon: string;
|
|
category: string;
|
|
}
|
|
|
|
// All apps below have real deployable templates in DashCaddy.
|
|
// Verified against src/docker/app-templates.js (93 templates, Aug 2026).
|
|
const apps: App[] = [
|
|
// Media
|
|
{ name: 'Plex', icon: '🎬', category: 'Media' },
|
|
{ name: 'Jellyfin', icon: '🍿', category: 'Media' },
|
|
{ name: 'Emby', icon: '🎥', category: 'Media' },
|
|
{ name: 'Navidrome', icon: '🎶', category: 'Media' },
|
|
{ name: 'Airsonic Advanced', icon: '🎧', category: 'Media' },
|
|
{ name: 'Audiobookshelf', icon: '🎧', category: 'Media' },
|
|
{ name: 'Calibre-Web', icon: '📖', category: 'Media' },
|
|
{ name: 'Komga', icon: '📚', category: 'Media' },
|
|
{ name: 'Kavita', icon: '📖', category: 'Media' },
|
|
{ name: 'Subsonic', icon: '🎵', category: 'Media' },
|
|
|
|
// Media Management
|
|
{ name: 'Sonarr', icon: '📺', category: 'Media Mgmt' },
|
|
{ name: 'Radarr', icon: '🎭', category: 'Media Mgmt' },
|
|
{ name: 'Prowlarr', icon: '🔍', category: 'Media Mgmt' },
|
|
{ name: 'Lidarr', icon: '🎵', category: 'Media Mgmt' },
|
|
{ name: 'Readarr', icon: '📚', category: 'Media Mgmt' },
|
|
{ name: 'Bazarr', icon: '💬', category: 'Media Mgmt' },
|
|
{ name: 'Seerr', icon: '🎫', category: 'Media Mgmt' },
|
|
{ name: 'Tautulli', icon: '📊', category: 'Media Mgmt' },
|
|
|
|
// Downloads
|
|
{ name: 'qBittorrent', icon: '⬇️', category: 'Downloads' },
|
|
{ name: 'SABnzbd', icon: '📰', category: 'Downloads' },
|
|
{ name: 'NZBGet', icon: '📥', category: 'Downloads' },
|
|
{ name: 'Transmission', icon: '🌊', category: 'Downloads' },
|
|
{ name: 'JDownloader 2', icon: '⬇️', category: 'Downloads' },
|
|
|
|
// Productivity
|
|
{ name: 'Nextcloud', icon: '☁️', category: 'Productivity' },
|
|
{ name: 'BookStack', icon: '📖', category: 'Productivity' },
|
|
{ name: 'Outline', icon: '📝', category: 'Productivity' },
|
|
{ name: 'Standard Notes', icon: '🔒', category: 'Productivity' },
|
|
{ name: 'Actual Budget', icon: '💰', category: 'Productivity' },
|
|
{ name: 'Mealie', icon: '🍳', category: 'Productivity' },
|
|
{ name: 'Paperless-ngx', icon: '📚', category: 'Productivity' },
|
|
{ name: 'Trilium Notes', icon: '🗒️', category: 'Productivity' },
|
|
{ name: 'Excalidraw', icon: '🎨', category: 'Productivity' },
|
|
{ name: 'HedgeDoc', icon: '📝', category: 'Productivity' },
|
|
{ name: 'OpenProject', icon: '📋', category: 'Productivity' },
|
|
{ name: 'Plane', icon: '✈️', category: 'Productivity' },
|
|
{ name: 'Vikunja', icon: '✅', category: 'Productivity' },
|
|
|
|
// Photos
|
|
{ name: 'Immich', icon: '📸', category: 'Photos' },
|
|
{ name: 'PhotoPrism', icon: '🖼️', category: 'Photos' },
|
|
|
|
// Files
|
|
{ name: 'FileBrowser', icon: '📁', category: 'Files' },
|
|
{ name: 'Syncthing', icon: '🔄', category: 'Files' },
|
|
{ name: 'Sami Files', icon: '📂', category: 'Files' },
|
|
|
|
// Management
|
|
{ name: 'Portainer', icon: '🐳', category: 'Management' },
|
|
{ name: 'Watchtower', icon: '👓', category: 'Management' },
|
|
{ name: 'Yacht', icon: '⛵', category: 'Management' },
|
|
|
|
// Security
|
|
{ name: 'Vaultwarden', icon: '🔑', category: 'Security' },
|
|
{ name: 'DashCA', icon: '🔐', category: 'Security' },
|
|
{ name: 'Authentik', icon: '🔐', category: 'Security' },
|
|
{ name: 'CrowdSec', icon: '🛡️', category: 'Security' },
|
|
{ name: 'Authelia', icon: '🔐', category: 'Security' },
|
|
{ name: 'Bitwarden', icon: '🔑', category: 'Security' },
|
|
{ name: 'Keycloak', icon: '🔑', category: 'Security' },
|
|
|
|
// Development
|
|
{ name: 'VS Code Server', icon: '💻', category: 'Development' },
|
|
{ name: 'Gitea', icon: '🦊', category: 'Development' },
|
|
{ name: 'Jenkins', icon: '🔧', category: 'Development' },
|
|
{ name: 'Drone CI', icon: '🐝', category: 'Development' },
|
|
{ name: 'Forgejo', icon: '🦊', category: 'Development' },
|
|
{ name: 'GitLab', icon: '🦊', category: 'Development' },
|
|
|
|
// Monitoring
|
|
{ name: 'Grafana', icon: '📊', category: 'Monitoring' },
|
|
{ name: 'Uptime Kuma', icon: '📈', category: 'Monitoring' },
|
|
{ name: 'Speedtest Tracker', icon: '⚡', category: 'Monitoring' },
|
|
{ name: 'Dozzle', icon: '📜', category: 'Monitoring' },
|
|
{ name: 'Kibana', icon: '📊', category: 'Monitoring' },
|
|
{ name: 'Netdata', icon: '📈', category: 'Monitoring' },
|
|
{ name: 'Prometheus', icon: '🔥', category: 'Monitoring' },
|
|
|
|
// Networking
|
|
{ name: 'Pi-hole', icon: '🛡️', category: 'Networking' },
|
|
{ name: 'WireGuard VPN', icon: '🔒', category: 'Networking' },
|
|
{ name: 'OpenVPN', icon: '🔒', category: 'Networking' },
|
|
|
|
// DNS
|
|
{ name: 'Technitium DNS Server', icon: '🌐', category: 'DNS' },
|
|
{ name: 'BIND9 DNS Server', icon: '🔧', category: 'DNS' },
|
|
{ name: 'PowerDNS', icon: '⚡', category: 'DNS' },
|
|
{ name: 'CoreDNS', icon: '☁️', category: 'DNS' },
|
|
|
|
// Communication
|
|
{ name: 'Docker Mailserver', icon: '📧', category: 'Communication' },
|
|
{ name: 'Roundcube', icon: '💌', category: 'Communication' },
|
|
{ name: 'Matrix Synapse', icon: '💬', category: 'Communication' },
|
|
{ name: 'Rocket.Chat', icon: '🚀', category: 'Communication' },
|
|
|
|
// Database
|
|
{ name: 'PostgreSQL', icon: '🐘', category: 'Database' },
|
|
{ name: 'Redis', icon: '🔴', category: 'Database' },
|
|
{ name: 'MongoDB', icon: '🍃', category: 'Database' },
|
|
{ name: 'Adminer', icon: '🗄️', category: 'Database' },
|
|
|
|
// Gaming
|
|
{ name: 'Minecraft Server', icon: '⛏️', category: 'Gaming' },
|
|
{ name: 'Valheim Server', icon: '⚔️', category: 'Gaming' },
|
|
|
|
// Home Automation
|
|
{ name: 'Home Assistant', icon: '🏠', category: 'Home Automation' },
|
|
{ name: 'Node-RED', icon: '🔴', category: 'Home Automation' },
|
|
{ name: 'OpenHAB', icon: '🏠', category: 'Home Automation' },
|
|
|
|
// Utilities
|
|
{ name: 'Weather', icon: '🌤️', category: 'Utilities' },
|
|
{ name: 'Digital Clock', icon: '🕐', category: 'Utilities' },
|
|
{ name: 'Homepage', icon: '🏡', category: 'Utilities' },
|
|
{ name: 'Homarr', icon: '🎯', category: 'Utilities' },
|
|
{ name: 'Change Detection', icon: '👁️', category: 'Utilities' },
|
|
{ name: 'Whoami', icon: '🔍', category: 'Utilities' },
|
|
{ name: 'Stirling PDF', icon: '📄', category: 'Utilities' },
|
|
{ name: 'IT Tools', icon: '🧰', category: 'Utilities' },
|
|
{ name: 'Vintage Stereo', icon: '📻', category: 'Utilities' },
|
|
];
|
|
|
|
const categories = [
|
|
'All',
|
|
'Media',
|
|
'Media Mgmt',
|
|
'Downloads',
|
|
'Productivity',
|
|
'Photos',
|
|
'Files',
|
|
'Management',
|
|
'Security',
|
|
'Development',
|
|
'Monitoring',
|
|
'Networking',
|
|
'DNS',
|
|
'Communication',
|
|
'Database',
|
|
'Gaming',
|
|
'Home Automation',
|
|
'Utilities',
|
|
];
|
|
|
|
export default function AppShowcase() {
|
|
const [activeCategory, setActiveCategory] = useState('All');
|
|
|
|
const filteredApps =
|
|
activeCategory === 'All'
|
|
? apps
|
|
: apps.filter((app) => app.category === activeCategory);
|
|
|
|
return (
|
|
<section className="relative py-12 px-4 sm:px-6 lg:px-8 bg-gradient-to-b from-surface-950 to-surface-900">
|
|
<div className="mx-auto max-w-7xl">
|
|
{/* Header */}
|
|
<div className="mb-12 text-center">
|
|
<h2 className="text-3xl sm:text-4xl font-bold text-surface-50 mb-4">
|
|
93 One-Click App Templates
|
|
</h2>
|
|
<p className="text-lg text-surface-400 max-w-2xl mx-auto">
|
|
Deploy your favorite apps instantly with pre-configured templates, automatic SSL certificates, and integrated DNS management.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Category Filter */}
|
|
<div className="mb-10 flex flex-wrap justify-center gap-2">
|
|
{categories.map((category) => (
|
|
<button
|
|
key={category}
|
|
onClick={() => setActiveCategory(category)}
|
|
className={`px-4 py-2 rounded-full text-sm font-medium transition-all duration-200 ${
|
|
activeCategory === category
|
|
? 'bg-brand-500 text-white shadow-lg shadow-brand-500/30'
|
|
: 'bg-surface-800 text-surface-300 hover:bg-surface-700 hover:text-surface-200'
|
|
}`}
|
|
>
|
|
{category}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{/* App Grid */}
|
|
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4">
|
|
{filteredApps.map((app) => (
|
|
<div
|
|
key={`${app.name}-${app.category}`}
|
|
className="group relative flex flex-col items-center justify-center rounded-lg border border-surface-700 bg-surface-800/50 backdrop-blur-sm p-4 transition-all duration-300 hover:border-brand-500/50 hover:bg-surface-800/80 hover:shadow-lg hover:shadow-brand-500/10 hover:-translate-y-1"
|
|
>
|
|
{/* Background gradient on hover */}
|
|
<div className="absolute inset-0 bg-gradient-to-br from-brand-500/0 to-brand-500/0 group-hover:from-brand-500/5 group-hover:to-brand-500/10 rounded-lg transition-all duration-300 pointer-events-none" />
|
|
|
|
<div className="relative z-10 flex flex-col items-center justify-center text-center">
|
|
{/* Icon */}
|
|
<div className="text-4xl mb-2 transition-transform duration-300 group-hover:scale-110">
|
|
{app.icon}
|
|
</div>
|
|
|
|
{/* App Name */}
|
|
<h3 className="text-sm font-semibold text-surface-50 line-clamp-2 group-hover:text-brand-400 transition-colors">
|
|
{app.name}
|
|
</h3>
|
|
|
|
{/* Category Tag */}
|
|
<span className="text-xs text-surface-500 mt-1 group-hover:text-brand-400/70">
|
|
{app.category}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Stats */}
|
|
<div className="mt-16 grid grid-cols-3 gap-4 sm:gap-8">
|
|
<div className="text-center">
|
|
<div className="text-3xl sm:text-4xl font-bold text-brand-400 mb-2">
|
|
93
|
|
</div>
|
|
<p className="text-sm text-surface-400">App Templates</p>
|
|
</div>
|
|
<div className="text-center">
|
|
<div className="text-3xl sm:text-4xl font-bold text-brand-400 mb-2">
|
|
0
|
|
</div>
|
|
<p className="text-sm text-surface-400">Configuration</p>
|
|
</div>
|
|
<div className="text-center">
|
|
<div className="text-3xl sm:text-4xl font-bold text-brand-400 mb-2">
|
|
1-Click
|
|
</div>
|
|
<p className="text-sm text-surface-400">Deploy</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|