commit e9f58520957028d6e7619264b316d04ba7caf024
parent fb1291eab9294a1c262c7007d822a287bef8faa4
Author: Hunter
Date:   Mon, 10 Nov 2025 23:59:25 -0500

support localhost installation/caching

Diffstat:
Mgenerate_manifests.py | 113++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Mhost.py | 31++++++++++++++++++++++++++++++-
2 files changed, 99 insertions(+), 45 deletions(-)

diff --git a/generate_manifests.py b/generate_manifests.py @@ -8,37 +8,54 @@ import json import re from pathlib import Path -def get_configuration(): - """Prompt user for configuration values""" +def get_configuration(localhost=False): + """Prompt user for configuration values + + Args: + localhost: If True, assumes root path and only asks for app name. + This enables PWA installation on localhost (iOS 18+). + """ print("=" * 60) print("PWA Configuration") print("=" * 60) print() # Get app name - app_name = input("Enter a name for your mixapp: ").strip() - if not app_name: - print("Error: App name is required") - exit(1) - - # Get base path with smart default - default_path = app_name.lower().replace(" ", "_") - print() - print(f"Enter the deployment path (or press Return/Enter for default)") - print(f"Default: /{default_path}/") - base_path_input = input("Path: ").strip() - - if base_path_input: - # User provided a path - ensure it has leading/trailing slashes - base_path = base_path_input - if not base_path.startswith("/"): - base_path = "/" + base_path - if not base_path.endswith("/"): - base_path = base_path + "/" + if localhost: + app_name = input("Enter a name for your mixapp (or press Return/Enter for 'vibe capsule'): ").strip() + if not app_name: + app_name = "vibe capsule" + print(f"Using default: {app_name}") else: - # Use default - base_path = f"/{default_path}/" - print(f"Using default path: {base_path}") + app_name = input("Enter a name for your mixapp: ").strip() + if not app_name: + print("Error: App name is required") + exit(1) + + # For localhost mode, use root path + if localhost: + base_path = "/" + print() + print("Localhost mode: Using root path for PWA installation") + else: + # Get base path with smart default + default_path = app_name.lower().replace(" ", "_") + print() + print(f"Enter the deployment path (or press Return/Enter for default)") + print(f"Default: /{default_path}/") + base_path_input = input("Path: ").strip() + + if base_path_input: + # User provided a path - ensure it has leading/trailing slashes + base_path = base_path_input + if not base_path.startswith("/"): + base_path = "/" + base_path + if not base_path.endswith("/"): + base_path = base_path + "/" + else: + # Use default + base_path = f"/{default_path}/" + print(f"Using default path: {base_path}") print() print(f"Configuration:") @@ -48,14 +65,6 @@ def get_configuration(): return app_name, base_path -# Get configuration from user -APP_NAME, BASE_PATH = get_configuration() - -# Derived values (can be manually overridden if desired) -SHORT_NAME = APP_NAME -CACHE_NAME = APP_NAME -APP_DESCRIPTION = f"{APP_NAME} · vibe capsule" - # File paths (no need to edit these) SCRIPT_DIR = Path(__file__).parent.absolute() TRACKS_JSON = SCRIPT_DIR / "tracks" / "tracks.json" @@ -85,8 +94,22 @@ def get_background_color(): return "#080a0c" -def generate_pwa_manifests(): - """Generate PWA manifest files based on tracks.json""" +def generate_pwa_manifests(app_name=None, base_path=None): + """Generate PWA manifest files based on tracks.json + + Args: + app_name: Name of the app. If None, will be prompted via get_configuration() + base_path: Base path for the app. If None, will be prompted via get_configuration() + """ + # Get configuration if not provided + if app_name is None or base_path is None: + app_name, base_path = get_configuration() + + # Derived values + short_name = app_name + cache_name = app_name + app_description = f"{app_name} · vibe capsule" + print("Generating PWA manifests...") # Load tracks.json @@ -102,16 +125,16 @@ def generate_pwa_manifests(): # Generate manifest.json manifest = { - "id": BASE_PATH, - "name": APP_NAME, - "short_name": SHORT_NAME, - "description": APP_DESCRIPTION, - "start_url": BASE_PATH, - "scope": BASE_PATH, + "id": base_path, + "name": app_name, + "short_name": short_name, + "description": app_description, + "start_url": base_path, + "scope": base_path, "display": "standalone", "background_color": background_color, "theme_color": background_color, - "cache_name": CACHE_NAME, # Custom field for script.js to use + "cache_name": cache_name, # Custom field for script.js to use "icons": [ { "src": "resources/icon.png", @@ -150,8 +173,8 @@ def generate_pwa_manifests(): # Generate service-worker.js static_files = resource_manifest["static_files"] - service_worker_content = f'''// Auto-generated service worker for {APP_NAME} PWA -const CACHE_NAME = '{CACHE_NAME}'; + service_worker_content = f'''// Auto-generated service worker for {app_name} PWA +const CACHE_NAME = '{cache_name}'; const staticFilesToCache = {json.dumps(static_files, indent=2)}; // Get the base path from the service worker location @@ -283,4 +306,6 @@ self.addEventListener('fetch', (event) => {{ if __name__ == "__main__": - generate_pwa_manifests() + # When run directly, get configuration and generate manifests + app_name, base_path = get_configuration() + generate_pwa_manifests(app_name, base_path) diff --git a/host.py b/host.py @@ -116,11 +116,40 @@ def print_qr_code(url): print(f"\nCould not generate QR code: {e}") +def generate_localhost_manifests(): + """Generate PWA manifests for localhost usage""" + try: + # Import the generate_manifests module + sys.path.insert(0, str(SCRIPT_DIR)) + from generate_manifests import get_configuration, generate_pwa_manifests + + # Get configuration with localhost mode enabled + print() + app_name, base_path = get_configuration(localhost=True) + + # Generate the manifests + generate_pwa_manifests(app_name, base_path) + print() + + return app_name + + except ImportError as e: + print(f"Error: Could not import generate_manifests.py: {e}") + print("Make sure generate_manifests.py is in the same directory.") + sys.exit(1) + except Exception as e: + print(f"Error generating manifests: {e}") + sys.exit(1) + + def start_server(): """Start the HTTP server (runs after venv is set up)""" # Change to script directory os.chdir(SCRIPT_DIR) + # Generate manifests for localhost + app_name = generate_localhost_manifests() + # Find an available port port = find_available_port(DEFAULT_PORT) @@ -153,7 +182,7 @@ def start_server(): network_url = f"http://{local_ip}:{port}" print("=" * 60) - print("💿 vibe capsule") + print(f"💿 {app_name}") print("=" * 60) print(f"\nServer running on port {port}")