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

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

AI Voice Designer: Custom Voice Generation Specification

This document details the design specifications, user interface (UI) wireframe descriptions, recommended color palettes, and user experience (UX) best practices for creating a completely custom AI voice using the ElevenLabs platform. The goal is to provide a highly intuitive and powerful tool that translates user-described characteristics into a unique AI voice.


1. Detailed Design Specifications: Voice Characteristics & Parameters

The custom AI voice design will be driven by a comprehensive set of parameters, allowing users to sculpt the voice's identity from the ground up. These parameters will be translated into ElevenLabs' advanced voice generation models.

1.1 Core Voice Identity

  • Gender:

* Options: Male, Female, Neutral/Androgynous.

* Fine-tuning: A slider for "Perceived Masculinity/Femininity" (0-100%) when "Neutral" or either gender is selected, allowing for nuanced expression.

  • Age Range:

* Options: Young Adult (18-30), Adult (30-50), Middle-aged (50-65), Senior (65+).

* Fine-tuning: A slider for "Perceived Age" within the selected range, offering more granular control (e.g., "early 30s" vs. "late 40s").

  • Accent/Dialect:

* Primary Region Selection: Dropdown with major categories (e.g., North American, British Isles, Australian/NZ, European, Asian).

* Specific Dialect Selection: Secondary dropdown based on primary region (e.g., for North American: General American, Southern US, New York, Canadian; for British Isles: RP, Northern English, Scottish, Irish).

* Intensity: A slider for "Accent Strength" (0-100%), allowing for subtle or pronounced accents.

1.2 Vocal Qualities & Expressiveness

  • Tone/Emotion:

* Descriptors (Multi-select/Sliders): Calm, Enthusiastic, Serious, Friendly, Authoritative, Warm, Playful, Empathetic, Sincere, Confident, Mysterious.

* Intensity Slider: For each selected descriptor, a slider (0-100%) to adjust its prominence.

* Emotional Range: A "Variance" slider to control how much the voice can naturally fluctuate in tone, from highly consistent to more dynamic.

  • Pacing:

* Slider: Slow, Moderate, Fast (0-100%).

  • Pitch:

* Slider: Low, Medium, High (0-100%).

* Range: A slider for "Pitch Variation," controlling the natural up-and-down movement in speech.

  • Volume:

* Slider: Soft, Normal, Loud (0-100%).

  • Resonance:

* Options (Radio Buttons/Sliders): Deep (chest voice), Clear (balanced), Breathy (airy), Nasal (more pronounced nasal cavity sound).

* Intensity Slider: For chosen resonance quality.

  • Vocal Texture/Quality:

* Descriptors (Multi-select): Smooth, Gritty, Husky, Crisp, Silky, Robust, Gentle.

* Intensity Slider: For each selected descriptor.

1.3 Intended Purpose & Context

  • Use Case: Dropdown with common applications (e.g., Narration, Conversational AI, Explainer Video, Character Voice, Customer Service, Podcast Host, Audiobooks). This helps the AI fine-tune the overall delivery style.

1.4 Unique Descriptors / "X-Factor"

  • Free-form Text Input: A large text area for users to describe unique or abstract characteristics not covered by the sliders (e.g., "a voice that sounds like a wise old mentor from a fantasy novel," "a slightly robotic but friendly voice," "a voice with a hint of a smile"). This input will be crucial for ElevenLabs' advanced generative capabilities.

2. Wireframe Descriptions: User Interface (UI) Elements

The UI will be designed for clarity, interactivity, and iterative refinement.

2.1 Layout Overview

  • Left Panel (Collapsible): Voice Parameter Controls (sliders, dropdowns, text input).
  • Central Panel: Sample Text Input, Playback Controls, Waveform Visualizer, Voice Name/ID Display.
  • Right Panel (Collapsible): Saved Voice Iterations/Comparison, Tips & Guidance.

2.2 Key UI Sections

  1. Voice Characteristics Panel (Left Panel):

* Header: "Design Your Custom Voice"

* Sections: Clearly delineated sections for "Core Identity," "Vocal Qualities," "Intended Purpose," and "Unique Descriptors."

* Input Elements:

* Sliders: For continuous parameters (Age, Pitch, Pacing, etc.) with numerical values and descriptive labels (e.g., "Low ↔ High").

* Dropdowns: For discrete choices (Gender, Accent Region/Dialect, Use Case).

* Multi-select Checkboxes/Buttons: For Tone/Emotion and Vocal Texture descriptors.

* Text Area: For "Unique Descriptors" with a character limit and example prompts.

* Reset Button: To clear all parameters and start fresh.

  1. Preview & Playback Panel (Central Panel):

* Sample Text Input: A multi-line text area where users type text to preview their custom voice.

Placeholder Text:* "Type some text here to hear your custom voice..."

Character Counter:* To indicate remaining characters.

* Play Button: Prominently displayed to generate and play the audio.

State Changes:* "Generate Voice" (initial) → "Generating..." (loading spinner) → "Play Voice" (after generation).

* Stop Button: To stop playback.

* Waveform Visualizer: A dynamic visual representation of the audio playback, enhancing the auditory experience.

* Voice Name/ID Display: Once generated, the system will assign a temporary name or ID (e.g., "Custom Voice 1") which the user can rename.

* Refinement Feedback: "Sounds good?" (Yes/No buttons) or a simple star rating to gather implicit feedback.

  1. Action & Management Panel (Bottom of Central Panel/Dedicated Section):

* Save Iteration Button: To save the current voice parameters and the generated audio for later comparison.

* Generate Final Voice Button: To finalize the voice design and add it to the user's voice library. This might trigger a more robust, higher-quality generation.

* Rename Button: To assign a custom name to the generated voice.

  1. Guidance & Comparison Panel (Right Panel - Collapsible):

* Tips & Examples: Contextual help for each parameter as the user hovers or selects it. Examples of different accent strengths, emotional tones, etc.

* Saved Voices List: A list of previously saved voice iterations with a small play button and a "Compare" option to switch between them easily.


3. Color Palettes

The color scheme will be professional, modern, and user-friendly, emphasizing clarity and interaction.

  • Primary Palette (Base & Backgrounds):

* #FFFFFF (White): Clean backgrounds, content areas.

* #F8F8F8 (Light Grey): Subtle section separators, hover states.

* #333333 (Dark Grey): Primary text, headings.

* #666666 (Medium Grey): Secondary text, labels.

  • Accent Palette (Interactive Elements & Branding):

* #007BFF (Vibrant Blue): Primary call-to-action buttons (e.g., "Generate Voice," "Save"), active states, progress bars.

* #28A745 (Success Green): Confirmation messages, "Generate Final Voice" button.

* #FFC107 (Warning Yellow): Informational alerts, subtle highlights.

* #17A2B8 (Teal/Cyan): Secondary interactive elements, waveform visualization.

  • Feedback & Status Colors:

* #DC3545 (Red): Error messages.

* #007BFF (Blue): Loading/processing indicators.


4. User Experience (UX) Recommendations

  • Iterative Design Cycle:

* Fast Previews: Optimize the "Play" function for rapid generation and playback of sample text, allowing users to quickly hear changes as they adjust parameters.

* Auto-Save Drafts: Automatically save user's current parameter settings as a draft to prevent loss of work.

  • Clear and Concise Language:

* Use simple, descriptive labels for all sliders, dropdowns, and buttons. Avoid jargon.

* Provide tooltips for complex parameters explaining their impact on the voice.

  • Visual Feedback:

* Loading Indicators: Use spinners or progress bars during voice generation.

* Active States: Clearly indicate selected options, hovered elements, and active sliders.

* Waveform Visualization: Provide a real-time (or near real-time) waveform display during playback to make the audio interaction more tangible.

  • Sensible Defaults & Guidance:

* Starting Point: Pre-select a "General American, Adult Female, Moderate" voice as a default to give users a familiar starting point.

* Contextual Help: Offer small "i" icons next to complex parameters that reveal detailed explanations or examples when clicked/hovered.

  • Comparison Functionality:

* Allow users to save multiple iterations of their voice design.

* Implement a "Compare" mode where users can easily switch between saved voices and hear the differences to refine their choice.

  • Accessibility:

* Ensure sufficient color contrast for all text and UI elements.

* Support keyboard navigation for all interactive components.

* Provide clear focus states for keyboard users.

  • Scalability for Future Features:

* Design the parameter panel to be extensible, allowing for the addition of new voice characteristics or advanced ElevenLabs features as they become available (e.g., specific emotional blend ratios, unique vocal effects).

  • Performance Optimization:

* Prioritize efficient backend processing for voice generation to minimize waiting times.

* Optimize frontend rendering to ensure a smooth, responsive UI even with many interactive elements.

This detailed specification provides a robust framework for developing an intuitive and powerful AI Voice Designer, empowering users to create truly custom voices tailored to their exact needs.

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);}});}