mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-23 03:27:43 +09:00
Initialize React dashboard project structure
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.
This commit is contained in:
1 parent
44a1dde4f4
commit
97a111feb7
17 files changed
+6141
No files matched your search
@@ -0,0 +1 @@
|
||||
/frontend/node_modules
|
||||
@@ -0,0 +1,482 @@
|
||||
<!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>
|
||||
@@ -0,0 +1,57 @@
|
||||
# Project Intent
|
||||
|
||||
## Purpose
|
||||
Provide project intent and behavioral expectations for Antigravity and Google models.
|
||||
|
||||
## Scope
|
||||
Model neutral guidance. No permissions. No Claude specific instructions.
|
||||
|
||||
## One Paragraph Project Summary
|
||||
This is a modern React dashboard application boilerplate built with Vite, featuring routing, charts, and a sidebar layout for building data-driven web interfaces.
|
||||
|
||||
## What the Project is For
|
||||
To serve as a starting template for building React dashboard applications, providing essential setup for development, building, and deployment with components for navigation, data visualization, and user management.
|
||||
|
||||
## Stability Guarantees
|
||||
- Uses stable versions of React, Vite, and related libraries
|
||||
- Follows standard project structures for dashboards
|
||||
- Includes routing and layout components
|
||||
|
||||
## Data Contracts and Invariants
|
||||
- Components expect standard React props
|
||||
- File structure adheres to src/ with App.jsx, main.jsx, components/, layouts/, pages/
|
||||
- Uses react-router-dom for routing
|
||||
- Charts use Recharts library
|
||||
- Icons from Lucide React
|
||||
|
||||
## Compatibility Expectations
|
||||
- Compatible with modern browsers and Node.js 16+
|
||||
- Follows web standards
|
||||
|
||||
## Risk Tolerance Level
|
||||
Low to medium - prefer proven libraries and avoid experimental features.
|
||||
|
||||
## What Changes are Considered Safe
|
||||
- Adding new components, layouts, or pages
|
||||
- Updating documentation
|
||||
- Minor style adjustments
|
||||
- Bug fixes in existing code
|
||||
- Adding new routes
|
||||
|
||||
## What Changes Require Explicit Approval
|
||||
- Major architectural changes
|
||||
- Upgrading major dependencies
|
||||
- Restructuring folders
|
||||
- Introducing new charting libraries
|
||||
- Removing existing routes or components
|
||||
|
||||
## Non Goals
|
||||
- Not intended for server-side rendering
|
||||
- Not a full-stack solution
|
||||
- Avoids complex state management libraries by default
|
||||
|
||||
## Important Notes
|
||||
Antigravity will also analyze README.md and other markdown documentation. This file clarifies intent, sets boundaries, and avoids duplicating documentation.
|
||||
|
||||
## Outcome
|
||||
Antigravity builds a correct mental model of the project before acting.
|
||||
@@ -0,0 +1,91 @@
|
||||
# React Dashboard Template
|
||||
|
||||
A modern React dashboard application boilerplate built with Vite, featuring routing, charts, and a sidebar layout for building data-driven web interfaces.
|
||||
|
||||
## Features
|
||||
|
||||
- **React 18** with functional components and hooks
|
||||
- **Vite** for fast development and building
|
||||
- **React Router** for client-side routing
|
||||
- **Recharts** for data visualization
|
||||
- **Lucide React** for icons
|
||||
- **ESLint** for code linting
|
||||
- Responsive sidebar layout
|
||||
- Dashboard page with sample components
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js 16+ and npm
|
||||
|
||||
### Installation
|
||||
|
||||
1. Clone or download this template
|
||||
2. Install dependencies:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### Development
|
||||
|
||||
Start the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
The app will be available at `http://localhost:5173`.
|
||||
|
||||
### Building for Production
|
||||
|
||||
Build the app for deployment:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The output will be in the `dist/` directory.
|
||||
|
||||
### Preview Production Build
|
||||
|
||||
```bash
|
||||
npm run preview
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── App.jsx # Main app with routing
|
||||
├── main.jsx # Entry point
|
||||
├── index.css # Global styles
|
||||
├── components/
|
||||
│ └── Sidebar.jsx # Navigation sidebar
|
||||
├── layouts/
|
||||
│ └── DashboardLayout.jsx # Main layout wrapper
|
||||
└── pages/
|
||||
└── Dashboard.jsx # Main dashboard page
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
- Modify components in `src/components/`
|
||||
- Add new pages in `src/pages/`
|
||||
- Update routes in `App.jsx`
|
||||
- Customize styles in `index.css` or component files
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Create a `.env` file in the root for environment variables:
|
||||
|
||||
```env
|
||||
VITE_API_URL=https://api.example.com
|
||||
```
|
||||
|
||||
Access them in code via `import.meta.env.VITE_API_URL`.
|
||||
|
||||
## Contributing
|
||||
|
||||
See the documentation files for AI agent permissions and guidelines.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Agents Permissions
|
||||
|
||||
## Purpose
|
||||
Establish strict permissions for any AI agent interacting with the repo.
|
||||
|
||||
## Scope
|
||||
Safety and authorization only. No style or philosophy.
|
||||
|
||||
## Allowed Read and Write Paths
|
||||
- `src/` (all files and subdirectories)
|
||||
- `index.html`
|
||||
- `package.json`
|
||||
- `vite.config.js`
|
||||
- `template.json`
|
||||
- `how_it_works.md`
|
||||
|
||||
## Explicitly Forbidden Actions
|
||||
- No file deletion
|
||||
- No renaming public APIs
|
||||
- No dependency upgrades
|
||||
- No folder restructuring
|
||||
- No shell execution unless explicitly requested
|
||||
- Minimal diffs only
|
||||
- JSON schemas are contracts
|
||||
- Refactors require explicit approval
|
||||
|
||||
## Outcome
|
||||
All agents know exactly what they can and cannot do before touching code.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Claude Style Guide
|
||||
|
||||
## Purpose
|
||||
Make Claude behave like a long-term contributor who already knows your preferences.
|
||||
|
||||
## Scope
|
||||
Claude only. Style, structure, and expectations.
|
||||
|
||||
## How You Structure Code
|
||||
- Use functional components with React hooks
|
||||
- Separate logic into custom hooks when reusable
|
||||
- Keep components small and focused
|
||||
- Organize files in src/ with clear subdirectories (components/, layouts/, pages/)
|
||||
|
||||
## Naming Conventions
|
||||
- PascalCase for component names (e.g., Sidebar.jsx)
|
||||
- camelCase for variables, functions, and files (e.g., main.jsx)
|
||||
- Descriptive names, avoid abbreviations
|
||||
|
||||
## Acceptable Abstractions
|
||||
- Custom hooks for shared logic
|
||||
- Context API for simple global state
|
||||
- Utility functions in separate files
|
||||
- Layout components for consistent structure
|
||||
|
||||
## What You Dislike
|
||||
- Magic numbers or unexplained constants
|
||||
- Over-engineering simple features
|
||||
- Silent refactors without clear reasoning
|
||||
- Deep nesting of components
|
||||
|
||||
## How You Want Diffs Scoped
|
||||
- One logical change per commit
|
||||
- Keep diffs minimal and focused
|
||||
- Explain changes in commit messages
|
||||
|
||||
## How JSON Should be Shaped
|
||||
- Use flat structures where possible
|
||||
- Consistent key naming (camelCase)
|
||||
- Avoid deeply nested objects
|
||||
|
||||
## What "Done" Means to You
|
||||
- Code compiles and runs without errors
|
||||
- Passes linting rules
|
||||
- Implements the requested feature correctly
|
||||
- Includes basic tests if applicable
|
||||
- Documentation updated if needed
|
||||
|
||||
## Outcome
|
||||
Claude outputs code that matches your thinking and style consistently.
|
||||
@@ -0,0 +1,69 @@
|
||||
# How It Works
|
||||
|
||||
This project was bootstrapped with a modern React boilerplate using **Vite**.
|
||||
|
||||
## 📂 Project Structure
|
||||
|
||||
```text
|
||||
project_name/
|
||||
├── index.html # Entry HTML file
|
||||
├── package.json # Dependencies and scripts
|
||||
├── vite.config.js # Vite configuration
|
||||
└── src/
|
||||
├── App.jsx # Main App component
|
||||
├── main.jsx # Entry point
|
||||
└── index.css # Global styles
|
||||
```
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
Install dependencies using npm:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### Development
|
||||
|
||||
Start the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
The app will be available at `http://localhost:5173`.
|
||||
|
||||
### Building for Production
|
||||
|
||||
Build the app for deployment:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The output will be in the `dist/` directory.
|
||||
|
||||
## 🛠 Features
|
||||
|
||||
- **Vite**: Ultra-fast development server and bundler.
|
||||
- **React**: Modern UI library.
|
||||
- **ESLint**: Code linting.
|
||||
- **Prettier**: Code formatting.
|
||||
|
||||
## 🔄 Customization
|
||||
|
||||
### Project Metadata
|
||||
|
||||
The project name and authors are automatically configured in `package.json` and generated files during initialization.
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Create a `.env` file in the root for environment variables:
|
||||
|
||||
```env
|
||||
VITE_API_URL=https://api.example.com
|
||||
```
|
||||
|
||||
Access them in code via `import.meta.env.VITE_API_URL`.
|
||||
@@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>React Dashboard Template</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Generated
+5093
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "react-dashboard-template",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^6.22.3",
|
||||
"recharts": "^2.12.3",
|
||||
"lucide-react": "^0.363.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"eslint": "^9.9.0",
|
||||
"eslint-plugin-react": "^7.35.0",
|
||||
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.9",
|
||||
"globals": "^15.9.0",
|
||||
"vite": "^5.4.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
|
||||
import DashboardLayout from './layouts/DashboardLayout';
|
||||
import Dashboard from './pages/Dashboard';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Router>
|
||||
<Routes>
|
||||
<Route path="/" element={<DashboardLayout />}>
|
||||
<Route index element={<Dashboard />} />
|
||||
<Route path="users" element={<div>Users Page</div>} />
|
||||
<Route path="settings" element={<div>Settings Page</div>} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { LayoutDashboard, Users, Settings } from 'lucide-react';
|
||||
|
||||
const Sidebar = () => {
|
||||
return (
|
||||
<div className="sidebar">
|
||||
<div className="sidebar-header">Admin</div>
|
||||
<nav>
|
||||
<Link to="/" className="nav-link">
|
||||
<LayoutDashboard size={20} />
|
||||
Dashboard
|
||||
</Link>
|
||||
<Link to="/users" className="nav-link">
|
||||
<Users size={20} />
|
||||
Users
|
||||
</Link>
|
||||
<Link to="/settings" className="nav-link">
|
||||
<Settings size={20} />
|
||||
Settings
|
||||
</Link>
|
||||
</nav>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
@@ -0,0 +1,93 @@
|
||||
:root {
|
||||
--primary-color: #3b82f6;
|
||||
--bg-color: #f3f4f6;
|
||||
--sidebar-width: 250px;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background-color: var(--bg-color);
|
||||
}
|
||||
|
||||
.dashboard-layout {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: var(--sidebar-width);
|
||||
background-color: white;
|
||||
border-right: 1px solid #e5e7eb;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 30px;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 15px;
|
||||
color: #4b5563;
|
||||
text-decoration: none;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 5px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.nav-link:hover {
|
||||
background-color: #eff6ff;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
padding: 30px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
margin-top: 0;
|
||||
color: #6b7280;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.card .value {
|
||||
font-size: 1.8rem;
|
||||
font-weight: bold;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
height: 400px;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import Sidebar from '../components/Sidebar';
|
||||
|
||||
const DashboardLayout = () => {
|
||||
return (
|
||||
<div className="dashboard-layout">
|
||||
<Sidebar />
|
||||
<main className="main-content">
|
||||
<div className="header">
|
||||
<h2>Dashboard</h2>
|
||||
</div>
|
||||
<Outlet />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DashboardLayout;
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App.jsx'
|
||||
import './index.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
@@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
|
||||
|
||||
const data = [
|
||||
{ name: 'Jan', uv: 4000, pv: 2400, amt: 2400 },
|
||||
{ name: 'Feb', uv: 3000, pv: 1398, amt: 2210 },
|
||||
{ name: 'Mar', uv: 2000, pv: 9800, amt: 2290 },
|
||||
{ name: 'Apr', uv: 2780, pv: 3908, amt: 2000 },
|
||||
{ name: 'May', uv: 1890, pv: 4800, amt: 2181 },
|
||||
{ name: 'Jun', uv: 2390, pv: 3800, amt: 2500 },
|
||||
{ name: 'Jul', uv: 3490, pv: 4300, amt: 2100 },
|
||||
];
|
||||
|
||||
const Dashboard = () => {
|
||||
return (
|
||||
<div>
|
||||
<div className="card-grid">
|
||||
<div className="card">
|
||||
<h3>Total Users</h3>
|
||||
<div className="value">1,234</div>
|
||||
</div>
|
||||
<div className="card">
|
||||
<h3>Revenue</h3>
|
||||
<div className="value">$45,678</div>
|
||||
</div>
|
||||
<div className="card">
|
||||
<h3>Active Sessions</h3>
|
||||
<div className="value">890</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="chart-container">
|
||||
<h3>Overview</h3>
|
||||
<ResponsiveContainer width="100%" height="90%">
|
||||
<BarChart data={data}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="name" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Bar dataKey="uv" fill="#3b82f6" />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Dashboard;
|
||||
@@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
})
|
||||
Reference in new issue
Block a user