mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-30 08:36:55 +09:00
Add initial project files for a modern React dashboard template using Vite. Includes documentation, configuration, and core frontend source files with sidebar layout, routing, and sample dashboard page.
482 lines
18 KiB
HTML
482 lines
18 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>JuanPilot | Infrastructure</title>
|
|
<style>
|
|
/* --- DESIGN SYSTEM --- */
|
|
:root {
|
|
--bg-body: #09090b; /* Zinc 950 */
|
|
--bg-sidebar: #0f0f11; /* Slightly lighter than body */
|
|
--bg-card: #18181b; /* Zinc 900 */
|
|
--bg-hover: #27272a; /* Zinc 800 */
|
|
|
|
--border-subtle: #27272a;
|
|
--border-active: #3f3f46;
|
|
|
|
--text-primary: #f4f4f5;
|
|
--text-secondary: #a1a1aa;
|
|
--text-tertiary: #71717a;
|
|
|
|
--accent-primary: #6366f1; /* Indigo 500 */
|
|
--accent-glow: rgba(99, 102, 241, 0.15);
|
|
|
|
--success: #10b981;
|
|
--warning: #f59e0b;
|
|
--danger: #ef4444;
|
|
|
|
--font-main: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
--sidebar-width: 280px;
|
|
}
|
|
|
|
* { margin: 0; padding: 0; box-sizing: border-box; outline: none; }
|
|
|
|
body {
|
|
background-color: var(--bg-body);
|
|
color: var(--text-primary);
|
|
font-family: var(--font-main);
|
|
display: flex;
|
|
min-height: 100vh;
|
|
font-size: 14px;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
/* --- ICONS (SVG Styling) --- */
|
|
svg {
|
|
width: 20px;
|
|
height: 20px;
|
|
stroke: currentColor;
|
|
stroke-width: 2;
|
|
stroke-linecap: round;
|
|
stroke-linejoin: round;
|
|
fill: none;
|
|
}
|
|
|
|
/* --- SIDEBAR --- */
|
|
.sidebar {
|
|
width: var(--sidebar-width);
|
|
background-color: var(--bg-sidebar);
|
|
border-right: 1px solid var(--border-subtle);
|
|
display: flex;
|
|
flex-direction: column;
|
|
position: fixed;
|
|
height: 100vh;
|
|
z-index: 10;
|
|
}
|
|
|
|
.brand {
|
|
padding: 24px 32px;
|
|
font-size: 16px;
|
|
font-weight: 700;
|
|
letter-spacing: -0.5px;
|
|
color: var(--text-primary);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
border-bottom: 1px solid var(--border-subtle);
|
|
}
|
|
|
|
.brand-logo {
|
|
width: 32px; height: 32px;
|
|
background: linear-gradient(135deg, var(--accent-primary), #818cf8);
|
|
border-radius: 8px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: white;
|
|
}
|
|
|
|
.menu-label {
|
|
padding: 24px 32px 8px;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
color: var(--text-tertiary);
|
|
}
|
|
|
|
.nav { display: flex; flex-direction: column; padding: 0 16px; gap: 4px; }
|
|
|
|
.nav-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
padding: 10px 16px;
|
|
color: var(--text-secondary);
|
|
text-decoration: none;
|
|
border-radius: 6px;
|
|
transition: all 0.2s ease;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.nav-item:hover {
|
|
background-color: var(--bg-hover);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.nav-item.active {
|
|
background-color: var(--accent-glow);
|
|
color: var(--accent-primary);
|
|
}
|
|
|
|
.user-profile {
|
|
margin-top: auto;
|
|
padding: 20px;
|
|
border-top: 1px solid var(--border-subtle);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
|
|
.avatar {
|
|
width: 36px; height: 36px;
|
|
background-color: var(--bg-hover);
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: var(--text-secondary);
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* --- MAIN AREA --- */
|
|
.main {
|
|
margin-left: var(--sidebar-width);
|
|
flex: 1;
|
|
padding: 40px;
|
|
}
|
|
|
|
.top-bar {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 40px;
|
|
}
|
|
|
|
h1 { font-size: 24px; font-weight: 600; letter-spacing: -0.5px; }
|
|
.subtitle { color: var(--text-tertiary); margin-top: 4px; }
|
|
|
|
.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 10px 20px;
|
|
border-radius: 8px;
|
|
border: 1px solid transparent;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: 0.2s;
|
|
}
|
|
|
|
.btn-primary {
|
|
background-color: var(--accent-primary);
|
|
color: white;
|
|
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
|
|
}
|
|
.btn-primary:hover { background-color: #4f46e5; }
|
|
|
|
.btn-secondary {
|
|
background-color: transparent;
|
|
border-color: var(--border-active);
|
|
color: var(--text-primary);
|
|
}
|
|
.btn-secondary:hover { background-color: var(--bg-hover); }
|
|
|
|
/* --- GRID LAYOUT --- */
|
|
.dashboard-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
|
|
gap: 24px;
|
|
}
|
|
|
|
.card {
|
|
background-color: var(--bg-card);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: 12px;
|
|
padding: 24px;
|
|
transition: transform 0.2s, border-color 0.2s;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.card:hover {
|
|
border-color: var(--border-active);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.card-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.app-icon {
|
|
width: 40px; height: 40px;
|
|
border-radius: 8px;
|
|
background-color: var(--bg-hover);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: var(--text-primary);
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.status-badge {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 4px 10px;
|
|
border-radius: 20px;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
border: 1px solid transparent;
|
|
}
|
|
|
|
.status-active { background: rgba(16, 185, 129, 0.1); color: var(--success); border-color: rgba(16, 185, 129, 0.2); }
|
|
.status-warning { background: rgba(245, 158, 11, 0.1); color: var(--warning); border-color: rgba(245, 158, 11, 0.2); }
|
|
|
|
.card h3 { font-size: 16px; font-weight: 600; color: var(--text-primary); margin-bottom: 4px; }
|
|
.card-link { color: var(--text-secondary); text-decoration: none; font-size: 13px; }
|
|
.card-link:hover { color: var(--accent-primary); }
|
|
|
|
.metric-row {
|
|
margin-top: 24px;
|
|
padding-top: 20px;
|
|
border-top: 1px solid var(--border-subtle);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
font-size: 12px;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.metric-item { display: flex; flex-direction: column; gap: 4px; }
|
|
.metric-value { font-weight: 600; color: var(--text-primary); font-family: monospace; }
|
|
|
|
/* --- STATS BAR (CPU/RAM) --- */
|
|
.stats-strip {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 24px;
|
|
margin-bottom: 32px;
|
|
}
|
|
|
|
.stat-card {
|
|
background: var(--bg-card);
|
|
padding: 20px;
|
|
border-radius: 12px;
|
|
border: 1px solid var(--border-subtle);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.stat-label { font-size: 12px; color: var(--text-tertiary); text-transform: uppercase; font-weight: 600; }
|
|
.stat-value { font-size: 20px; font-weight: 700; color: var(--text-primary); }
|
|
|
|
.progress-bar {
|
|
height: 4px;
|
|
background: var(--bg-hover);
|
|
border-radius: 2px;
|
|
overflow: hidden;
|
|
margin-top: 4px;
|
|
}
|
|
.progress-fill { height: 100%; border-radius: 2px; }
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<aside class="sidebar">
|
|
<div class="brand">
|
|
<div class="brand-logo">
|
|
<svg viewBox="0 0 24 24"><path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/></svg>
|
|
</div>
|
|
JuanPilot
|
|
</div>
|
|
|
|
<div class="menu-label">Overview</div>
|
|
<nav class="nav">
|
|
<a href="#" class="nav-item active">
|
|
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect></svg>
|
|
Dashboard
|
|
</a>
|
|
<a href="#" class="nav-item">
|
|
<svg viewBox="0 0 24 24"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline></svg>
|
|
Activity
|
|
</a>
|
|
</nav>
|
|
|
|
<div class="menu-label">Infrastructure</div>
|
|
<nav class="nav">
|
|
<a href="#" class="nav-item">
|
|
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path></svg>
|
|
Domains & Sites
|
|
</a>
|
|
<a href="#" class="nav-item">
|
|
<svg viewBox="0 0 24 24"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path><polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline><line x1="12" y1="22.08" x2="12" y2="12"></line></svg>
|
|
Applications
|
|
</a>
|
|
<a href="#" class="nav-item">
|
|
<svg viewBox="0 0 24 24"><ellipse cx="12" cy="5" rx="9" ry="3"></ellipse><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path></svg>
|
|
Databases
|
|
</a>
|
|
<a href="#" class="nav-item">
|
|
<svg viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
|
|
SSL Certificates
|
|
</a>
|
|
</nav>
|
|
|
|
<div class="menu-label">System</div>
|
|
<nav class="nav">
|
|
<a href="#" class="nav-item">
|
|
<svg viewBox="0 0 24 24"><path d="M4 17l6-6-6-6M12 19h8"/></svg>
|
|
Terminal / Logs
|
|
</a>
|
|
<a href="#" class="nav-item">
|
|
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
|
Settings
|
|
</a>
|
|
</nav>
|
|
|
|
<div class="user-profile">
|
|
<div class="avatar">JD</div>
|
|
<div style="font-size: 13px;">
|
|
<div style="font-weight: 600;">Juan Denis</div>
|
|
<div style="color: var(--text-tertiary);">Admin</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
|
|
<main class="main">
|
|
<header class="top-bar">
|
|
<div>
|
|
<h1>Dashboard</h1>
|
|
<div class="subtitle">Overview of your droplet status and applications.</div>
|
|
</div>
|
|
<div style="display: flex; gap: 12px;">
|
|
<button class="btn btn-secondary">
|
|
<svg viewBox="0 0 24 24"><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path></svg>
|
|
Logs
|
|
</button>
|
|
<button class="btn btn-primary">
|
|
<svg viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
|
|
New Application
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<section class="stats-strip">
|
|
<div class="stat-card">
|
|
<div class="stat-label">CPU Usage</div>
|
|
<div class="stat-value">12%</div>
|
|
<div class="progress-bar"><div class="progress-fill" style="width: 12%; background: var(--success);"></div></div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-label">Memory</div>
|
|
<div class="stat-value">1.8GB <span style="font-size: 14px; color: var(--text-tertiary);">/ 4GB</span></div>
|
|
<div class="progress-bar"><div class="progress-fill" style="width: 45%; background: var(--accent-primary);"></div></div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-label">Disk Space</div>
|
|
<div class="stat-value">22GB <span style="font-size: 14px; color: var(--text-tertiary);">/ 80GB</span></div>
|
|
<div class="progress-bar"><div class="progress-fill" style="width: 27%; background: var(--accent-primary);"></div></div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-label">Load Average</div>
|
|
<div class="stat-value">0.45</div>
|
|
<div class="progress-bar"><div class="progress-fill" style="width: 10%; background: var(--success);"></div></div>
|
|
</div>
|
|
</section>
|
|
|
|
<h2 style="font-size: 18px; margin-bottom: 20px; font-weight: 600;">Active Projects</h2>
|
|
<div class="dashboard-grid">
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<div class="app-icon">
|
|
<svg viewBox="0 0 24 24" width="24" height="24"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
|
|
</div>
|
|
<div class="status-badge status-active">
|
|
<div style="width: 6px; height: 6px; background: currentColor; border-radius: 50%;"></div>
|
|
Running
|
|
</div>
|
|
</div>
|
|
<h3>juandenis.com</h3>
|
|
<a href="#" class="card-link">https://juandenis.com</a>
|
|
<div class="metric-row">
|
|
<div class="metric-item">
|
|
<span>Stack</span>
|
|
<span class="metric-value" style="color: #a78bfa;">WP / PHP 8.2</span>
|
|
</div>
|
|
<div class="metric-item">
|
|
<span>Uptime</span>
|
|
<span class="metric-value">14d 2h</span>
|
|
</div>
|
|
<div class="metric-item">
|
|
<button class="btn btn-secondary" style="padding: 4px 8px; font-size: 11px;">Manage</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<div class="app-icon">
|
|
<svg viewBox="0 0 24 24" width="24" height="24"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>
|
|
</div>
|
|
<div class="status-badge status-active">
|
|
<div style="width: 6px; height: 6px; background: currentColor; border-radius: 50%;"></div>
|
|
Running
|
|
</div>
|
|
</div>
|
|
<h3>api.samanlabs.com</h3>
|
|
<a href="#" class="card-link">https://api.samanlabs.com</a>
|
|
<div class="metric-row">
|
|
<div class="metric-item">
|
|
<span>Stack</span>
|
|
<span class="metric-value" style="color: #fcd34d;">Python / Flask</span>
|
|
</div>
|
|
<div class="metric-item">
|
|
<span>Port</span>
|
|
<span class="metric-value">8000</span>
|
|
</div>
|
|
<div class="metric-item">
|
|
<button class="btn btn-secondary" style="padding: 4px 8px; font-size: 11px;">Manage</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<div class="app-icon">
|
|
<svg viewBox="0 0 24 24" width="24" height="24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path></svg>
|
|
</div>
|
|
<div class="status-badge status-warning">
|
|
<div style="width: 6px; height: 6px; background: currentColor; border-radius: 50%;"></div>
|
|
Syncing
|
|
</div>
|
|
</div>
|
|
<h3>cecileblin.com</h3>
|
|
<a href="#" class="card-link">https://cecileblin.com</a>
|
|
<div class="metric-row">
|
|
<div class="metric-item">
|
|
<span>Stack</span>
|
|
<span class="metric-value" style="color: #60a5fa;">Static / HTML</span>
|
|
</div>
|
|
<div class="metric-item">
|
|
<span>Last Deploy</span>
|
|
<span class="metric-value">2m ago</span>
|
|
</div>
|
|
<div class="metric-item">
|
|
<button class="btn btn-secondary" style="padding: 4px 8px; font-size: 11px;">Manage</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</main>
|
|
|
|
</body>
|
|
</html> |