PWA, server needs to serve via HTTPS still
9
web/public/browserconfig.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/icons/icon-144x144.png"/>
|
||||
<TileColor>#1e1e1e</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
BIN
web/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
web/public/icons/icon-128x128.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
web/public/icons/icon-144x144.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
web/public/icons/icon-152x152.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
web/public/icons/icon-16x16.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
web/public/icons/icon-180x180.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web/public/icons/icon-192x192.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web/public/icons/icon-32x32.png
Normal file
|
After Width: | Height: | Size: 3 KiB |
BIN
web/public/icons/icon-384x384.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
web/public/icons/icon-512x512.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
web/public/icons/icon-72x72.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
web/public/icons/icon-96x96.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
42
web/public/icons/icon.svg
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<defs>
|
||||
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#007acc;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#005a9e;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="512" height="512" rx="64" ry="64" fill="#1e1e1e"/>
|
||||
|
||||
<!-- Terminal window -->
|
||||
<rect x="64" y="96" width="384" height="288" rx="16" ry="16" fill="#2d2d30" stroke="#007acc" stroke-width="2"/>
|
||||
|
||||
<!-- Terminal header -->
|
||||
<rect x="64" y="96" width="384" height="48" rx="16" ry="16" fill="url(#grad1)"/>
|
||||
<rect x="64" y="128" width="384" height="16" fill="url(#grad1)"/>
|
||||
|
||||
<!-- Window controls -->
|
||||
<circle cx="96" cy="120" r="6" fill="#ff5f57"/>
|
||||
<circle cx="120" cy="120" r="6" fill="#ffbd2e"/>
|
||||
<circle cx="144" cy="120" r="6" fill="#28ca42"/>
|
||||
|
||||
<!-- Terminal content lines -->
|
||||
<rect x="96" y="168" width="320" height="8" rx="4" fill="#007acc"/>
|
||||
<rect x="96" y="188" width="280" height="8" rx="4" fill="#4fc1ff"/>
|
||||
<rect x="96" y="208" width="300" height="8" rx="4" fill="#007acc"/>
|
||||
<rect x="96" y="228" width="200" height="8" rx="4" fill="#4fc1ff"/>
|
||||
|
||||
<!-- Cursor -->
|
||||
<rect x="224" y="248" width="12" height="16" fill="#00ff00" opacity="0.8"/>
|
||||
|
||||
<!-- Connection lines (representing tunnel/multiplexing) -->
|
||||
<path d="M 256 400 Q 180 420 120 450" stroke="#007acc" stroke-width="4" fill="none" opacity="0.6"/>
|
||||
<path d="M 256 400 Q 332 420 392 450" stroke="#007acc" stroke-width="4" fill="none" opacity="0.6"/>
|
||||
<path d="M 256 400 Q 256 430 256 460" stroke="#007acc" stroke-width="4" fill="none" opacity="0.6"/>
|
||||
|
||||
<!-- Connection endpoints -->
|
||||
<circle cx="120" cy="450" r="8" fill="#007acc"/>
|
||||
<circle cx="256" cy="460" r="8" fill="#007acc"/>
|
||||
<circle cx="392" cy="450" r="8" fill="#007acc"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
|
|
@ -4,8 +4,41 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>VibeTunnel - Terminal Multiplexer</title>
|
||||
<meta name="description" content="Interactive terminal sessions in your browser with real-time streaming and mobile support">
|
||||
|
||||
<!-- PWA Manifest -->
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
|
||||
<!-- Theme colors -->
|
||||
<meta name="theme-color" content="#007acc">
|
||||
<meta name="msapplication-TileColor" content="#1e1e1e">
|
||||
<meta name="msapplication-config" content="/browserconfig.xml">
|
||||
|
||||
<!-- Apple Touch Icons -->
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/icons/icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/icons/icon-180x180.png">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="apple-mobile-web-app-title" content="VibeTunnel">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/icons/icon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/icons/icon-16x16.png">
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
|
||||
<!-- Open Graph / Social Media -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="VibeTunnel - Terminal Multiplexer">
|
||||
<meta property="og:description" content="Interactive terminal sessions in your browser with real-time streaming and mobile support">
|
||||
<meta property="og:image" content="/icons/icon-512x512.png">
|
||||
<meta property="og:url" content="/">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/asciinema-player@3.7.0/dist/bundle/asciinema-player.css" />
|
||||
<link href="output.css" rel="stylesheet">
|
||||
|
||||
<!-- Import Maps -->
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
|
|
@ -19,5 +52,76 @@
|
|||
<vibetunnel-app></vibetunnel-app>
|
||||
<script src="https://unpkg.com/asciinema-player@3.7.0/dist/bundle/asciinema-player.min.js"></script>
|
||||
<script type="module" src="app-entry.js"></script>
|
||||
|
||||
<!-- Service Worker Registration -->
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('/sw.js')
|
||||
.then((registration) => {
|
||||
console.log('PWA: Service Worker registered successfully:', registration.scope);
|
||||
|
||||
// Check for updates
|
||||
registration.addEventListener('updatefound', () => {
|
||||
const newWorker = registration.installing;
|
||||
if (newWorker) {
|
||||
newWorker.addEventListener('statechange', () => {
|
||||
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
|
||||
// New update available
|
||||
console.log('PWA: New version available');
|
||||
// You could show a notification here to reload
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('PWA: Service Worker registration failed:', error);
|
||||
});
|
||||
});
|
||||
|
||||
// Listen for messages from service worker
|
||||
navigator.serviceWorker.addEventListener('message', (event) => {
|
||||
if (event.data && event.data.type === 'CACHE_UPDATED') {
|
||||
console.log('PWA: Cache updated');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Handle install prompt
|
||||
let deferredPrompt;
|
||||
window.addEventListener('beforeinstallprompt', (e) => {
|
||||
console.log('PWA: Install prompt available - you can install VibeTunnel!');
|
||||
// Prevent Chrome 67 and earlier from automatically showing the prompt
|
||||
e.preventDefault();
|
||||
// Stash the event so it can be triggered later
|
||||
deferredPrompt = e;
|
||||
|
||||
// Show a temporary notification that install is available
|
||||
console.log('PWA: App can be installed - look for the install icon in your browser!');
|
||||
|
||||
// You can trigger the install prompt manually like this:
|
||||
// deferredPrompt.prompt();
|
||||
});
|
||||
|
||||
window.addEventListener('appinstalled', (evt) => {
|
||||
console.log('PWA: App was installed successfully');
|
||||
});
|
||||
|
||||
// Debug PWA readiness
|
||||
window.addEventListener('load', () => {
|
||||
// Check PWA criteria
|
||||
console.log('PWA Debug Info:');
|
||||
console.log('- HTTPS:', window.location.protocol === 'https:');
|
||||
console.log('- Service Worker supported:', 'serviceWorker' in navigator);
|
||||
console.log('- Manifest link present:', !!document.querySelector('link[rel="manifest"]'));
|
||||
console.log('- Current URL:', window.location.href);
|
||||
|
||||
// Check if already installed
|
||||
if (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches) {
|
||||
console.log('PWA: App is running in standalone mode (already installed)');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
93
web/public/manifest.json
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"name": "VibeTunnel",
|
||||
"short_name": "VibeTunnel",
|
||||
"description": "Interactive terminal sessions in your browser",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#1e1e1e",
|
||||
"theme_color": "#007acc",
|
||||
"orientation": "any",
|
||||
"scope": "/",
|
||||
"categories": ["developer", "utilities"],
|
||||
"lang": "en-US",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icons/icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/icons/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/icons/icon-128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/icons/icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/icons/icon-152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/icons/icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/icons/icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/icons/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
}
|
||||
],
|
||||
"shortcuts": [
|
||||
{
|
||||
"name": "New Session",
|
||||
"short_name": "New",
|
||||
"description": "Create a new terminal session",
|
||||
"url": "/?action=create",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icons/icon-96x96.png",
|
||||
"sizes": "96x96"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"screenshots": [
|
||||
{
|
||||
"src": "/screenshots/desktop.png",
|
||||
"sizes": "1280x720",
|
||||
"type": "image/png",
|
||||
"form_factor": "wide",
|
||||
"label": "VibeTunnel desktop view"
|
||||
},
|
||||
{
|
||||
"src": "/screenshots/mobile.png",
|
||||
"sizes": "390x844",
|
||||
"type": "image/png",
|
||||
"form_factor": "narrow",
|
||||
"label": "VibeTunnel mobile view"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
web/public/screenshots/desktop.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
5
web/public/screenshots/desktop.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720">
|
||||
<!-- Desktop screenshot placeholder -->
|
||||
<rect width="1280" height="720" fill="#1e1e1e"/>
|
||||
<text x="640" y="360" text-anchor="middle" fill="#007acc" font-family="monospace" font-size="32">VibeTunnel Desktop View</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 293 B |
BIN
web/public/screenshots/mobile.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
5
web/public/screenshots/mobile.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 390 844">
|
||||
<!-- Mobile screenshot placeholder -->
|
||||
<rect width="390" height="844" fill="#1e1e1e"/>
|
||||
<text x="195" y="422" text-anchor="middle" fill="#007acc" font-family="monospace" font-size="16">VibeTunnel Mobile View</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 289 B |