AI Voice Designer
Run ID: 69cc86a83e7fb09ff16a2afc2026-04-01Design
PantheraHive BOS
BOS Dashboard

Design a completely custom AI voice by describing the characteristics you want

AI Voice Designer: Comprehensive UI/UX Design Proposal

This document outlines a comprehensive design proposal for an "AI Voice Designer" interface, enabling users to create completely custom AI voices by describing their desired characteristics. The design focuses on intuitive interaction, detailed customization, and real-time feedback, leveraging advanced AI voice synthesis capabilities (e.g., ElevenLabs).


1. Executive Summary

The AI Voice Designer aims to provide a user-friendly and powerful platform for crafting unique synthetic voices. By offering a blend of intuitive characteristic sliders, descriptive text input, and real-time audio preview, the tool empowers users to precisely define and generate voices tailored to their specific needs. This proposal details the interface's design specifications, user experience flow, visual aesthetics, and technical considerations to deliver a professional and highly effective voice creation experience.


2. Core Concept & Objectives

Core Concept: An interactive, multi-modal interface that translates user-defined voice characteristics into a custom AI voice, offering immediate auditory feedback and iterative refinement capabilities.

Objectives:

  • Empowerment: Allow users to design voices without requiring deep technical knowledge of voice synthesis.
  • Precision: Provide granular control over various voice attributes.
  • Efficiency: Enable quick iteration and real-time preview of changes.
  • Professionalism: Deliver high-quality, natural-sounding custom voices suitable for various applications.
  • Usability: Ensure a clear, intuitive, and engaging user experience.

3. Detailed Design Specifications

The AI Voice Designer will feature a robust set of functionalities, blending quantitative and qualitative input methods.

3.1. Feature Set

  • Characteristic Sliders: Adjustable parameters for core voice attributes (e.g., Pitch, Speed, Volume, Resonance, Warmth, Age, Gender Spectrum).
  • Descriptive Text Input: A natural language processing (NLP) powered text field for users to describe nuanced characteristics (e.g., "a wise old mentor," "an enthusiastic young professional," "a calm and soothing storyteller").
  • Voice Style Presets: A library of predefined voice archetypes as starting points (e.g., Narrator, Announcer, Conversational, Character).
  • Emotion Modulators: Sliders or discrete selections for injecting specific emotions (e.g., Happy, Sad, Angry, Neutral, Excited, Calm).
  • Accent & Language Selection: Dropdown for supported accents and languages.
  • Real-time Text-to-Speech (TTS) Preview: An integrated text box for users to type and hear their custom voice instantly.
  • Voice Comparison: Ability to compare the current custom voice with existing voices or previous iterations.
  • Voice Cloning/Sampling (Advanced): Option to upload an audio sample to extract and adapt characteristics, or clone a voice (with explicit consent and legal compliance).
  • Save & Manage Voices: Functionality to save custom voice profiles for future use, editing, and deployment.
  • Export Options: Various formats (e.g., MP3, WAV) and API integration details for generated voices.

3.2. Input Modalities

  • Sliders: For continuous numerical parameters (Pitch, Speed, Volume, etc.).
  • Dropdowns/Radio Buttons: For discrete choices (Gender Spectrum, Accent, Language).
  • Text Area: For descriptive natural language input (e.g., "describe desired characteristics").
  • Toggle Switches: For binary options (e.g., "enhance clarity," "add reverb").
  • Audio Upload: For voice cloning or characteristic extraction.

3.3. Output & Preview

  • Audio Playback Button: Clearly visible button to trigger TTS preview.
  • Waveform Visualization: A small, dynamic waveform display during playback for visual feedback.
  • Voice Profile Summary: A textual summary of the current voice's parameters and NLP-derived characteristics.
  • Voice ID/API Key: Upon saving, the system will provide a unique identifier and relevant API information for integration.

4. Wireframe Descriptions

The interface will be organized into a logical flow, typically a three-column or two-column layout with a prominent central canvas.

4.1. Main Voice Design Canvas (Central Panel)

  • Layout: Dominant central area.
  • Elements:

* Text-to-Speech Input Box: A large, multi-line text area at the top, labeled "Type to Preview Your Voice." Includes a character counter.

* Play Button: A prominent, universally recognized play icon (e.g., triangle) positioned below or beside the text box.

* Audio Waveform Display: A dynamic visualizer that appears during playback, offering instant feedback.

* Voice Profile Summary: A concise text block summarizing the current voice's key characteristics, dynamically updating as sliders or text inputs change.

* "Generate Voice" / "Save Voice" Button: A primary call to action, typically at the bottom right.

4.2. Characteristics Control Panel (Left Panel)

  • Layout: A collapsible or fixed left sidebar.
  • Sections:

* "Core Attributes" (Sliders):

* Pitch: Slider with range (e.g., -10 to +10 semitones).

* Speed: Slider with range (e.g., 0.5x to 2.0x).

* Volume: Slider with range (e.g., 50% to 150%).

* Resonance/Formant: Slider for vocal tract shaping.

* Warmth/Brightness: Slider for tone quality.

* Age: Slider (e.g., Young, Adult, Mature).

* Gender Spectrum: Slider (e.g., Feminine to Masculine, with a Neutral midpoint).

* "Style & Emotion" (Pickers/Sliders):

* Emotion: Dropdown or discrete buttons (e.g., Happy, Sad, Angry, Calm, Neutral, Excited).

* Accent: Dropdown (e.g., US English, UK English, Australian, Indian).

* Language: Dropdown (e.g., English, Spanish, German, French).

* "Descriptive Input":

* Text Area: "Describe your desired voice characteristics here..." (e.g., "A deep, resonant voice with a calm, authoritative tone, suitable for narration.").

* "Analyze/Apply" Button: Triggers NLP processing and applies characteristics.

4.3. Voice Management & Presets (Right Panel)

  • Layout: A collapsible or fixed right sidebar.
  • Sections:

* "Voice Presets":

* A grid or list of curated voice archetypes (e.g., "Default Narrator," "Friendly AI," "Authoritative Speaker"). Clicking a preset loads its parameters.

* "My Saved Voices":

* A list of user's previously saved custom voices. Each entry includes voice name, a small play icon for preview, and an "Edit" button.

* "Advanced Options":

* Voice Cloning/Sampling: "Upload Audio Sample" button with drag-and-drop area.

* Noise Reduction/Reverb: Toggle switches or simple sliders.

* "Export & API":

* "Export Audio" button (with format options).

* "Get API Key / Integration Details" button.


5. Color Palette

The chosen color palette aims for professionalism, clarity, and a modern aesthetic, while ensuring good contrast and accessibility.

  • Primary Brand Color: #007BFF (Vibrant Blue) - Used for primary call-to-action buttons, active states, and key highlights.
  • Secondary Accent Color: #28A745 (Success Green) - Used for save confirmations, successful operations, or positive feedback.
  • Neutral Backgrounds:

* #F8F9FA (Light Gray) - Main background for panels and containers.

* #FFFFFF (White) - Background for input fields, cards, and primary content areas.

  • Typography Colors:

* #212529 (Dark Gray) - Main text, headings for readability.

* #6C757D (Medium Gray) - Secondary text, labels, hints.

  • Interactive Elements:

* #0056B3 (Darker Blue) - Hover state for primary buttons.

* #E9ECEF (Lighter Gray) - Hover state for list items, non-primary buttons.

  • Error/Warning: #DC3545 (Red) / #FFC107 (Yellow) - For error messages or warnings.

Rationale: The blue provides a sense of trust and technology, while the neutral grays and white ensure a clean, uncluttered interface. Green is a universal indicator of success, and the darker text colors provide high contrast for readability.


6. UX Recommendations

6.1. User Flow

  1. Start: User lands on the AI Voice Designer page.
  2. Initial Exploration: User sees default voice settings or selects a preset from the right panel.
  3. Preview: User types text into the TTS input box and clicks "Play" to hear the default/preset voice.
  4. Customization (Iterative):

* Sliders: User adjusts sliders in the left panel (Pitch, Speed, etc.). Each adjustment triggers a subtle visual update in the Voice Profile Summary.

* Descriptive Input: User types descriptive characteristics. An "Apply" or "Analyze" button processes the text, and the sliders may subtly adjust to reflect the NLP interpretation.

* Emotion/Accent: User selects desired emotion or accent.

* Re-preview: User clicks "Play" again to hear the changes. This cycle repeats until satisfied.

  1. Refinement: User might compare their custom voice to another preset or a previous saved version.
  2. Save: User clicks "Save Voice," provides a name, and the voice is added to "My Saved Voices."
  3. Deployment: User accesses "Export & API" for integration details or audio download.

6.2. Feedback Mechanisms

  • Real-time Audio: The most critical feedback, ensuring immediate hearing of changes.
  • Visual Updates: Sliders, text fields, and the voice summary panel should dynamically update to reflect all changes.
  • Loading Indicators: Brief spinners or progress bars during voice generation (especially for longer text or complex NLP processing).
  • Success/Error Messages: Clear, non-intrusive toasts or banners for actions like saving, exporting, or errors during generation.
  • Haptic Feedback (if applicable): Subtle vibrations on mobile devices for key interactions.

6.3. Accessibility

  • Keyboard Navigation: All interactive elements should be reachable and operable via keyboard.
  • Screen Reader Compatibility: Use proper ARIA attributes and semantic HTML for screen reader users.
  • Color Contrast: Adhere to WCAG guidelines for color contrast ratios for text and interactive elements.
  • Adjustable Text Size: Allow users to scale text size without breaking the layout.
  • Clear Labeling: All sliders, inputs, and buttons must have clear, descriptive labels.

6.4. Guidance & Tooltips

  • Onboarding Tour: A brief, optional tour for first-time users explaining the main sections.
  • Contextual Tooltips: Hovering over sliders or complex options should display a tooltip explaining what the parameter controls and its typical impact (e.g., "Pitch:
ai_voice_designer.md
Download as Markdown
Copy all content
Full output as text
Download ZIP
IDE-ready project ZIP
Copy share link
Permanent URL for this run
Get Embed Code
Embed this result on any website
Print / Save PDF
Use browser print dialog
"); var hasSrcMain=Object.keys(extracted).some(function(k){return k.indexOf("src/main")>=0;}); if(!hasSrcMain) zip.file(folder+"src/main."+ext,"import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import './index.css' ReactDOM.createRoot(document.getElementById('root')!).render( ) "); var hasSrcApp=Object.keys(extracted).some(function(k){return k==="src/App."+ext||k==="App."+ext;}); if(!hasSrcApp) zip.file(folder+"src/App."+ext,"import React from 'react' import './App.css' function App(){ return(

"+slugTitle(pn)+"

Built with PantheraHive BOS

) } export default App "); zip.file(folder+"src/index.css","*{margin:0;padding:0;box-sizing:border-box} body{font-family:system-ui,-apple-system,sans-serif;background:#f0f2f5;color:#1a1a2e} .app{min-height:100vh;display:flex;flex-direction:column} .app-header{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:40px} h1{font-size:2.5rem;font-weight:700} "); zip.file(folder+"src/App.css",""); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/pages/.gitkeep",""); zip.file(folder+"src/hooks/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+" Generated by PantheraHive BOS. ## Setup ```bash npm install npm run dev ``` ## Build ```bash npm run build ``` ## Open in IDE Open the project folder in VS Code or WebStorm. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local "); } /* --- Vue (Vite + Composition API + TypeScript) --- */ function buildVue(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{ "name": "'+pn+'", "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vue-tsc -b && vite build", "preview": "vite preview" }, "dependencies": { "vue": "^3.5.13", "vue-router": "^4.4.5", "pinia": "^2.3.0", "axios": "^1.7.9" }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", "typescript": "~5.7.3", "vite": "^6.0.5", "vue-tsc": "^2.2.0" } } '); zip.file(folder+"vite.config.ts","import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from 'path' export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': resolve(__dirname,'src') } } }) "); zip.file(folder+"tsconfig.json",'{"files":[],"references":[{"path":"./tsconfig.app.json"},{"path":"./tsconfig.node.json"}]} '); zip.file(folder+"tsconfig.app.json",'{ "compilerOptions":{ "target":"ES2020","useDefineForClassFields":true,"module":"ESNext","lib":["ES2020","DOM","DOM.Iterable"], "skipLibCheck":true,"moduleResolution":"bundler","allowImportingTsExtensions":true, "isolatedModules":true,"moduleDetection":"force","noEmit":true,"jsxImportSource":"vue", "strict":true,"paths":{"@/*":["./src/*"]} }, "include":["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"] } '); zip.file(folder+"env.d.ts","/// "); zip.file(folder+"index.html"," "+slugTitle(pn)+"
"); var hasMain=Object.keys(extracted).some(function(k){return k==="src/main.ts"||k==="main.ts";}); if(!hasMain) zip.file(folder+"src/main.ts","import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' import './assets/main.css' const app = createApp(App) app.use(createPinia()) app.mount('#app') "); var hasApp=Object.keys(extracted).some(function(k){return k.indexOf("App.vue")>=0;}); if(!hasApp) zip.file(folder+"src/App.vue"," "); zip.file(folder+"src/assets/main.css","*{margin:0;padding:0;box-sizing:border-box}body{font-family:system-ui,sans-serif;background:#fff;color:#213547} "); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/views/.gitkeep",""); zip.file(folder+"src/stores/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+" Generated by PantheraHive BOS. ## Setup ```bash npm install npm run dev ``` ## Build ```bash npm run build ``` Open in VS Code or WebStorm. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local "); } /* --- Angular (v19 standalone) --- */ function buildAngular(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var sel=pn.replace(/_/g,"-"); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{ "name": "'+pn+'", "version": "0.0.0", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test" }, "dependencies": { "@angular/animations": "^19.0.0", "@angular/common": "^19.0.0", "@angular/compiler": "^19.0.0", "@angular/core": "^19.0.0", "@angular/forms": "^19.0.0", "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.15.0" }, "devDependencies": { "@angular-devkit/build-angular": "^19.0.0", "@angular/cli": "^19.0.0", "@angular/compiler-cli": "^19.0.0", "typescript": "~5.6.0" } } '); zip.file(folder+"angular.json",'{ "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { "'+pn+'": { "projectType": "application", "root": "", "sourceRoot": "src", "prefix": "app", "architect": { "build": { "builder": "@angular-devkit/build-angular:application", "options": { "outputPath": "dist/'+pn+'", "index": "src/index.html", "browser": "src/main.ts", "tsConfig": "tsconfig.app.json", "styles": ["src/styles.css"], "scripts": [] } }, "serve": {"builder":"@angular-devkit/build-angular:dev-server","configurations":{"production":{"buildTarget":"'+pn+':build:production"},"development":{"buildTarget":"'+pn+':build:development"}},"defaultConfiguration":"development"} } } } } '); zip.file(folder+"tsconfig.json",'{ "compileOnSave": false, "compilerOptions": {"baseUrl":"./","outDir":"./dist/out-tsc","forceConsistentCasingInFileNames":true,"strict":true,"noImplicitOverride":true,"noPropertyAccessFromIndexSignature":true,"noImplicitReturns":true,"noFallthroughCasesInSwitch":true,"paths":{"@/*":["src/*"]},"skipLibCheck":true,"esModuleInterop":true,"sourceMap":true,"declaration":false,"experimentalDecorators":true,"moduleResolution":"bundler","importHelpers":true,"target":"ES2022","module":"ES2022","useDefineForClassFields":false,"lib":["ES2022","dom"]}, "references":[{"path":"./tsconfig.app.json"}] } '); zip.file(folder+"tsconfig.app.json",'{ "extends":"./tsconfig.json", "compilerOptions":{"outDir":"./dist/out-tsc","types":[]}, "files":["src/main.ts"], "include":["src/**/*.d.ts"] } '); zip.file(folder+"src/index.html"," "+slugTitle(pn)+" "); zip.file(folder+"src/main.ts","import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import { AppComponent } from './app/app.component'; bootstrapApplication(AppComponent, appConfig) .catch(err => console.error(err)); "); zip.file(folder+"src/styles.css","* { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: system-ui, -apple-system, sans-serif; background: #f9fafb; color: #111827; } "); var hasComp=Object.keys(extracted).some(function(k){return k.indexOf("app.component")>=0;}); if(!hasComp){ zip.file(folder+"src/app/app.component.ts","import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet], templateUrl: './app.component.html', styleUrl: './app.component.css' }) export class AppComponent { title = '"+pn+"'; } "); zip.file(folder+"src/app/app.component.html","

"+slugTitle(pn)+"

Built with PantheraHive BOS

"); zip.file(folder+"src/app/app.component.css",".app-header{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:60vh;gap:16px}h1{font-size:2.5rem;font-weight:700;color:#6366f1} "); } zip.file(folder+"src/app/app.config.ts","import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes) ] }; "); zip.file(folder+"src/app/app.routes.ts","import { Routes } from '@angular/router'; export const routes: Routes = []; "); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+" Generated by PantheraHive BOS. ## Setup ```bash npm install ng serve # or: npm start ``` ## Build ```bash ng build ``` Open in VS Code with Angular Language Service extension. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local .angular/ "); } /* --- Python --- */ function buildPython(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^```[w]* ?/m,"").replace(/ ?```$/m,"").trim(); var reqMap={"numpy":"numpy","pandas":"pandas","sklearn":"scikit-learn","tensorflow":"tensorflow","torch":"torch","flask":"flask","fastapi":"fastapi","uvicorn":"uvicorn","requests":"requests","sqlalchemy":"sqlalchemy","pydantic":"pydantic","dotenv":"python-dotenv","PIL":"Pillow","cv2":"opencv-python","matplotlib":"matplotlib","seaborn":"seaborn","scipy":"scipy"}; var reqs=[]; Object.keys(reqMap).forEach(function(k){if(src.indexOf("import "+k)>=0||src.indexOf("from "+k)>=0)reqs.push(reqMap[k]);}); var reqsTxt=reqs.length?reqs.join(" "):"# add dependencies here "; zip.file(folder+"main.py",src||"# "+title+" # Generated by PantheraHive BOS print(title+" loaded") "); zip.file(folder+"requirements.txt",reqsTxt); zip.file(folder+".env.example","# Environment variables "); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Setup ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ## Run ```bash python main.py ``` "); zip.file(folder+".gitignore",".venv/ __pycache__/ *.pyc .env .DS_Store "); } /* --- Node.js --- */ function buildNode(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^```[w]* ?/m,"").replace(/ ?```$/m,"").trim(); var depMap={"mongoose":"^8.0.0","dotenv":"^16.4.5","axios":"^1.7.9","cors":"^2.8.5","bcryptjs":"^2.4.3","jsonwebtoken":"^9.0.2","socket.io":"^4.7.4","uuid":"^9.0.1","zod":"^3.22.4","express":"^4.18.2"}; var deps={}; Object.keys(depMap).forEach(function(k){if(src.indexOf(k)>=0)deps[k]=depMap[k];}); if(!deps["express"])deps["express"]="^4.18.2"; var pkgJson=JSON.stringify({"name":pn,"version":"1.0.0","main":"src/index.js","scripts":{"start":"node src/index.js","dev":"nodemon src/index.js"},"dependencies":deps,"devDependencies":{"nodemon":"^3.0.3"}},null,2)+" "; zip.file(folder+"package.json",pkgJson); var fallback="const express=require("express"); const app=express(); app.use(express.json()); app.get("/",(req,res)=>{ res.json({message:""+title+" API"}); }); const PORT=process.env.PORT||3000; app.listen(PORT,()=>console.log("Server on port "+PORT)); "; zip.file(folder+"src/index.js",src||fallback); zip.file(folder+".env.example","PORT=3000 "); zip.file(folder+".gitignore","node_modules/ .env .DS_Store "); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Setup ```bash npm install ``` ## Run ```bash npm run dev ``` "); } /* --- Vanilla HTML --- */ function buildVanillaHtml(zip,folder,app,code){ var title=slugTitle(app); var isFullDoc=code.trim().toLowerCase().indexOf("=0||code.trim().toLowerCase().indexOf("=0; var indexHtml=isFullDoc?code:" "+title+" "+code+" "; zip.file(folder+"index.html",indexHtml); zip.file(folder+"style.css","/* "+title+" — styles */ *{margin:0;padding:0;box-sizing:border-box} body{font-family:system-ui,-apple-system,sans-serif;background:#fff;color:#1a1a2e} "); zip.file(folder+"script.js","/* "+title+" — scripts */ "); zip.file(folder+"assets/.gitkeep",""); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Open Double-click `index.html` in your browser. Or serve locally: ```bash npx serve . # or python3 -m http.server 3000 ``` "); zip.file(folder+".gitignore",".DS_Store node_modules/ .env "); } /* ===== MAIN ===== */ var sc=document.createElement("script"); sc.src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"; sc.onerror=function(){ if(lbl)lbl.textContent="Download ZIP"; alert("JSZip load failed — check connection."); }; sc.onload=function(){ var zip=new JSZip(); var base=(_phFname||"output").replace(/.[^.]+$/,""); var app=base.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")||"my_app"; var folder=app+"/"; var vc=document.getElementById("panel-content"); var panelTxt=vc?(vc.innerText||vc.textContent||""):""; var lang=detectLang(_phCode,panelTxt); if(_phIsHtml){ buildVanillaHtml(zip,folder,app,_phCode); } else if(lang==="flutter"){ buildFlutter(zip,folder,app,_phCode,panelTxt); } else if(lang==="react-native"){ buildReactNative(zip,folder,app,_phCode,panelTxt); } else if(lang==="swift"){ buildSwift(zip,folder,app,_phCode,panelTxt); } else if(lang==="kotlin"){ buildKotlin(zip,folder,app,_phCode,panelTxt); } else if(lang==="react"){ buildReact(zip,folder,app,_phCode,panelTxt); } else if(lang==="vue"){ buildVue(zip,folder,app,_phCode,panelTxt); } else if(lang==="angular"){ buildAngular(zip,folder,app,_phCode,panelTxt); } else if(lang==="python"){ buildPython(zip,folder,app,_phCode); } else if(lang==="node"){ buildNode(zip,folder,app,_phCode); } else { /* Document/content workflow */ var title=app.replace(/_/g," "); var md=_phAll||_phCode||panelTxt||"No content"; zip.file(folder+app+".md",md); var h=""+title+""; h+="

"+title+"

"; var hc=md.replace(/&/g,"&").replace(//g,">"); hc=hc.replace(/^### (.+)$/gm,"

$1

"); hc=hc.replace(/^## (.+)$/gm,"

$1

"); hc=hc.replace(/^# (.+)$/gm,"

$1

"); hc=hc.replace(/**(.+?)**/g,"$1"); hc=hc.replace(/ {2,}/g,"

"); h+="

"+hc+"

Generated by PantheraHive BOS
"; zip.file(folder+app+".html",h); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. Files: - "+app+".md (Markdown) - "+app+".html (styled HTML) "); } zip.generateAsync({type:"blob"}).then(function(blob){ var a=document.createElement("a"); a.href=URL.createObjectURL(blob); a.download=app+".zip"; a.click(); URL.revokeObjectURL(a.href); if(lbl)lbl.textContent="Download ZIP"; }); }; document.head.appendChild(sc); }function phShare(){navigator.clipboard.writeText(window.location.href).then(function(){var el=document.getElementById("ph-share-lbl");if(el){el.textContent="Link copied!";setTimeout(function(){el.textContent="Copy share link";},2500);}});}function phEmbed(){var runId=window.location.pathname.split("/").pop().replace(".html","");var embedUrl="https://pantherahive.com/embed/"+runId;var code='';navigator.clipboard.writeText(code).then(function(){var el=document.getElementById("ph-embed-lbl");if(el){el.textContent="Embed code copied!";setTimeout(function(){el.textContent="Get Embed Code";},2500);}});}