mirror of
https://github.com/jlengrand/Maestro.git
synced 2026-03-10 00:21:21 +00:00
* docs: add git hash display and configurable dev server port ## CHANGES - Add `VITE_PORT` env variable to configure dev server port - Display git commit hash in About modal next to version - Add `__GIT_HASH__` build-time constant to both Vite configs - Document running multiple Maestro instances with git worktrees - Update CONTRIBUTING.md with parallel development instructions * feat: add configurable ports for dev servers - Allow VITE_PORT to configure main dev server port - Update main window to load from configurable port - Enable VITE_WEB_PORT for web interface dev server - Add note in CONTRIBUTING.md about port configuration - Log port usage in development mode * docs: update CONTRIBUTING.md section and fix React DevTools script initialization ## CHANGES - Rename "Linting" section to "Linting & Pre-commit Hooks" in table of contents - Move script variable declaration outside conditional block - Fix React DevTools script initialization order in index.html * chore: update `.vscode/settings.json` with new markdownlint config * fix: disable biome linting. Project uses ESLint * chore: Update baseline-browser-mapping (>2 months old, warning message on "npm run build:web") * chore: add .vscode/ to gitignore * chore: fix gitignore to ignore .cscode/* files properly * fix * chore: stop tracking .vscode/ files, respect gitignore Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
225 lines
7.1 KiB
HTML
225 lines
7.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Maestro - Agent Orchestration Command Center</title>
|
|
|
|
<!-- Preload fonts to prevent FOUT (Flash of Unstyled Text) -->
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link rel="preload" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" as="style">
|
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
|
|
<!-- Critical CSS for splash screen - inline to prevent FOUC -->
|
|
<style>
|
|
/* Reset and base styles */
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html, body, #root {
|
|
width: 100%;
|
|
height: 100%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
body {
|
|
font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
|
|
-webkit-font-smoothing: antialiased;
|
|
-moz-osx-font-smoothing: grayscale;
|
|
background-color: #1a1a2e;
|
|
}
|
|
|
|
/* Initial splash screen styles */
|
|
#initial-splash {
|
|
position: fixed;
|
|
inset: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 9999;
|
|
background-color: #1a1a2e;
|
|
transition: opacity 0.5s ease-out;
|
|
/* Account for 40px title bar (pt-10) so content aligns with app layout */
|
|
padding-top: 40px;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
#initial-splash.hidden {
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.splash-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 32px;
|
|
}
|
|
|
|
.splash-logo {
|
|
width: 180px;
|
|
height: 180px;
|
|
border-radius: 24px;
|
|
box-shadow: 0 25px 50px -12px rgba(139, 92, 246, 0.4);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.splash-logo img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.splash-title {
|
|
font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
|
|
font-weight: 700;
|
|
font-size: 36px;
|
|
letter-spacing: 0.25em;
|
|
color: #ffffff;
|
|
text-shadow: 0 2px 10px rgba(139, 92, 246, 0.3);
|
|
}
|
|
|
|
.splash-progress-container {
|
|
width: 280px;
|
|
height: 6px;
|
|
background-color: rgba(255, 255, 255, 0.1);
|
|
border-radius: 9999px;
|
|
overflow: hidden;
|
|
position: relative;
|
|
}
|
|
|
|
.splash-progress-bar {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
height: 100%;
|
|
border-radius: 9999px;
|
|
background: linear-gradient(90deg, #8b5cf6 0%, #a78bfa 50%, #c4b5fd 100%);
|
|
box-shadow: 0 0 10px rgba(139, 92, 246, 0.5);
|
|
transition: width 0.15s ease-out;
|
|
width: 0%;
|
|
}
|
|
|
|
.splash-text {
|
|
font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
|
|
font-size: 14px;
|
|
letter-spacing: 0.05em;
|
|
color: rgba(255, 255, 255, 0.5);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<!-- Initial splash screen shown immediately while React loads -->
|
|
<div id="initial-splash">
|
|
<div class="splash-container">
|
|
<!-- Logo container with app icon -->
|
|
<div class="splash-logo">
|
|
<img src="/icon.png" alt="Maestro" />
|
|
</div>
|
|
|
|
<!-- Maestro title -->
|
|
<h1 class="splash-title">MAESTRO</h1>
|
|
|
|
<!-- Progress bar -->
|
|
<div class="splash-progress-container">
|
|
<div id="splash-progress" class="splash-progress-bar"></div>
|
|
</div>
|
|
|
|
<!-- Loading text -->
|
|
<p id="splash-text" class="splash-text">Loading...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="root"></div>
|
|
|
|
<!-- Splash screen progress animation -->
|
|
<script>
|
|
(function() {
|
|
var progress = 0;
|
|
var progressBar = document.getElementById('splash-progress');
|
|
var progressText = document.getElementById('splash-text');
|
|
|
|
// Capture any errors and display them on the splash screen
|
|
window.onerror = function(message, source, lineno, colno, error) {
|
|
if (progressText) {
|
|
progressText.style.color = '#ff6b6b';
|
|
progressText.textContent = 'Error: ' + (error?.message || message);
|
|
}
|
|
console.error('[Splash] Error:', message, source, lineno, colno, error);
|
|
return false;
|
|
};
|
|
window.onunhandledrejection = function(event) {
|
|
if (progressText) {
|
|
progressText.style.color = '#ff6b6b';
|
|
progressText.textContent = 'Error: ' + (event.reason?.message || String(event.reason));
|
|
}
|
|
console.error('[Splash] Unhandled rejection:', event.reason);
|
|
};
|
|
|
|
// Animate progress bar while waiting for React
|
|
var interval = setInterval(function() {
|
|
// Slow progress that caps at 70% until React takes over
|
|
progress += Math.random() * 3 + 1;
|
|
if (progress > 70) progress = 70;
|
|
if (progressBar) progressBar.style.width = progress + '%';
|
|
}, 100);
|
|
|
|
// Store interval ID so React can clear it
|
|
window.__splashInterval = interval;
|
|
window.__splashProgress = function() { return progress; };
|
|
|
|
// Function for React to call when ready
|
|
window.__hideSplash = function() {
|
|
clearInterval(interval);
|
|
|
|
// Complete the progress bar
|
|
if (progressBar) progressBar.style.width = '100%';
|
|
if (progressText) progressText.textContent = 'Ready';
|
|
|
|
// Helper to fade out the splash
|
|
function fadeOut() {
|
|
var splash = document.getElementById('initial-splash');
|
|
if (splash) {
|
|
splash.classList.add('hidden');
|
|
// Remove from DOM after animation
|
|
setTimeout(function() {
|
|
if (splash && splash.parentNode) {
|
|
splash.parentNode.removeChild(splash);
|
|
}
|
|
}, 500);
|
|
}
|
|
}
|
|
|
|
// Wait for fonts to be loaded to prevent layout shift from font swap
|
|
if (document.fonts && document.fonts.ready) {
|
|
document.fonts.ready.then(function() {
|
|
// Small delay after fonts ready for any final layout settling
|
|
setTimeout(fadeOut, 50);
|
|
});
|
|
} else {
|
|
// Fallback for browsers without Font Loading API
|
|
setTimeout(fadeOut, 200);
|
|
}
|
|
};
|
|
})();
|
|
</script>
|
|
|
|
<!-- React DevTools: connects to standalone react-devtools app (npm install -g react-devtools) -->
|
|
<!-- Only attempts connection in dev mode (Vite serves on localhost:5173) -->
|
|
<script>
|
|
var script = document.createElement('script');
|
|
if (window.location.hostname === 'localhost') {
|
|
script.src = 'http://localhost:8097';
|
|
script.async = false;
|
|
document.head.appendChild(script);
|
|
}
|
|
</script>
|
|
|
|
<script type="module" src="/main.tsx"></script>
|
|
</body>
|
|
</html>
|