138 lines
5.7 KiB
HTML
138 lines
5.7 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>StackPilot — Docker Stack Builder</title>
|
|
<link rel="icon" href="/favicon.svg" />
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
<link rel="stylesheet" href="/src/style.css" />
|
|
</head>
|
|
<body>
|
|
<header class="header">
|
|
<h1>🚀 StackPilot</h1>
|
|
<p class="subtitle">Build your self-hosted Docker stack in minutes</p>
|
|
<nav class="mode-nav">
|
|
<button class="mode-btn active" data-mode="builder">Stack Builder</button>
|
|
<button class="mode-btn" data-mode="analyser">Compose Analyser</button>
|
|
</nav>
|
|
</header>
|
|
|
|
<main class="container">
|
|
<!-- Step 1: Global Config -->
|
|
<section class="step" id="step-config">
|
|
<h2>1. Configure Paths</h2>
|
|
<div class="os-selector">
|
|
<label class="os-option">
|
|
<input type="radio" name="os" value="linux" checked />
|
|
<span class="os-label">🐧 Linux</span>
|
|
</label>
|
|
<label class="os-option">
|
|
<input type="radio" name="os" value="macos" />
|
|
<span class="os-label">🍎 macOS</span>
|
|
</label>
|
|
<label class="os-option">
|
|
<input type="radio" name="os" value="windows" />
|
|
<span class="os-label">🪟 Windows</span>
|
|
</label>
|
|
</div>
|
|
<div class="config-grid">
|
|
<label>
|
|
<span>Config path</span>
|
|
<input type="text" id="config-path" value="/opt/stackpilot/config" placeholder="/opt/stackpilot/config" />
|
|
</label>
|
|
<label>
|
|
<span>Media path</span>
|
|
<input type="text" id="media-path" value="/mnt/media" placeholder="/mnt/media" />
|
|
</label>
|
|
<label>
|
|
<span>Downloads path</span>
|
|
<input type="text" id="downloads-path" value="/mnt/downloads" placeholder="/mnt/downloads" />
|
|
</label>
|
|
<label>
|
|
<span>Timezone</span>
|
|
<input type="text" id="timezone" value="Europe/Dublin" placeholder="Europe/London" />
|
|
</label>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Step 2: App Selection -->
|
|
<section class="step" id="step-apps">
|
|
<h2>2. Select Apps</h2>
|
|
<div id="app-grid"></div>
|
|
</section>
|
|
|
|
<!-- Step 3: Tailscale Remote Access -->
|
|
<section class="step" id="step-tailscale">
|
|
<h2>3. Remote Access (Optional)</h2>
|
|
<div class="tailscale-config">
|
|
<label class="toggle-row">
|
|
<input type="checkbox" id="tailscale-enable" />
|
|
<span>Enable Tailscale — access your services from anywhere</span>
|
|
</label>
|
|
<div class="tailscale-options hidden" id="tailscale-options">
|
|
<div class="config-grid">
|
|
<label>
|
|
<span>Tailscale Auth Key</span>
|
|
<input type="text" id="ts-authkey" placeholder="tskey-auth-..." />
|
|
</label>
|
|
<label>
|
|
<span>Hostname</span>
|
|
<input type="text" id="ts-hostname" value="stackpilot" placeholder="stackpilot" />
|
|
</label>
|
|
</div>
|
|
<label class="toggle-row sub">
|
|
<input type="checkbox" id="ts-funnel" />
|
|
<span>Enable Tailscale Funnel (expose selected services to the internet)</span>
|
|
</label>
|
|
<label class="toggle-row sub">
|
|
<input type="checkbox" id="ts-subnet" checked />
|
|
<span>Advertise as subnet router (access all services via Tailscale IP)</span>
|
|
</label>
|
|
<div class="ts-warning">
|
|
⚠️ Security note: Tailscale Funnel exposes services publicly. Subnet routing only shares with your Tailnet (your devices).
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Step 4: Preview & Download -->
|
|
<section class="step" id="step-preview">
|
|
<h2>4. Preview & Download</h2>
|
|
<div class="preview-area">
|
|
<div class="preview-tabs">
|
|
<button class="tab active" data-tab="compose">docker-compose.yml</button>
|
|
<button class="tab" data-tab="env">.env</button>
|
|
<button class="tab" data-tab="setup">setup.sh</button>
|
|
</div>
|
|
<pre class="preview-code"><code id="preview-content">Select apps above to see preview...</code></pre>
|
|
</div>
|
|
<button class="download-btn" id="download-btn" disabled>📦 Download Stack Bundle (.zip)</button>
|
|
</section>
|
|
</main>
|
|
|
|
<footer class="footer">
|
|
<p>StackPilot — No server required. Everything runs in your browser.</p>
|
|
</footer>
|
|
|
|
<!-- Compose Analyser Modal/Section -->
|
|
<section class="step" id="step-analyser" style="display:none;">
|
|
<h2>🔍 Analyse Existing Docker Compose</h2>
|
|
<p class="analyser-desc">Paste your existing docker-compose.yml below to get security, performance, and best-practice recommendations.</p>
|
|
<textarea id="analyser-input" class="analyser-textarea" placeholder="Paste your docker-compose.yml here..."></textarea>
|
|
<button class="analyse-btn" id="analyse-btn">Analyse</button>
|
|
<div id="analyser-results" class="analyser-results"></div>
|
|
<button class="analyse-btn fixed-btn hidden" id="show-fixed-btn">✨ Show Fixed Compose</button>
|
|
<div id="fixed-preview" class="fixed-preview hidden">
|
|
<h3>Improved docker-compose.yml</h3>
|
|
<pre class="preview-code"><code id="fixed-content"></code></pre>
|
|
<button class="download-btn" id="download-fixed-btn" style="margin-top:1rem;">📦 Download Fixed Compose</button>
|
|
</div>
|
|
</section>
|
|
|
|
<script type="module" src="/src/main.js"></script>
|
|
</body>
|
|
</html>
|