AI Voice Designer
Run ID: 69cb90a861b1021a29a8a3972026-03-31Design
PantheraHive BOS
BOS Dashboard

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

AI Voice Designer: Detailed Professional Output

This document outlines the detailed design specifications, wireframe descriptions, color palette, and user experience (UX) recommendations for a custom AI Voice Designer tool. The goal is to provide a comprehensive and intuitive interface for users to create bespoke AI voices by describing their desired characteristics.


1. Detailed Design Specifications

The AI Voice Designer will empower users to craft unique voices through a combination of adjustable parameters, descriptive text inputs, and iterative refinement.

1.1 Core Voice Attribute Parameters

These are fundamental sliders and dropdowns for initial voice shaping.

  • Gender:

* Control: Slider (Female ↔ Male) with a neutral center point.

* Range: Continuous spectrum, allowing for nuanced gender expression rather than binary choices.

  • Age:

* Control: Slider (Young Child ↔ Elderly Adult).

* Range: Visual markers for common age groups (e.g., "Child," "Teen," "Young Adult," "Middle-aged," "Senior").

  • Pitch:

* Control: Slider (Very Low ↔ Very High).

* Range: Hz or semitone indicators for advanced users, but primarily descriptive labels.

  • Pace/Speed:

* Control: Slider (Very Slow ↔ Very Fast).

* Range: Words Per Minute (WPM) approximation for context.

  • Volume/Loudness:

* Control: Slider (Whisper ↔ Shout).

* Range: Decibel (dB) approximation for context.

1.2 Emotional Range & Style Parameters

These parameters allow for fine-tuning the expressive qualities of the voice.

  • Emotional Tendency:

* Control: Multi-select checkboxes or a "mood board" interface for primary emotions (e.g., Happy, Sad, Calm, Excited, Serious, Playful, Authoritative, Empathetic).

* Detail: Each selected emotion could have a sub-slider for intensity (e.g., "Slightly Happy" to "Very Happy").

  • Speaking Style:

* Control: Dropdown or radio buttons for common archetypes (e.g., Conversational, Narrative, Announcer, Instructional, Persuasive, Dramatic, Monotone).

* Detail: A free-text field for "Custom Style" for more specific descriptions (e.g., "like a wise old mentor," "energetic podcast host").

  • Intonation:

* Control: Slider (Monotone ↔ Highly Expressive).

* Detail: Influences the rise and fall of pitch in sentences.

1.3 Accent & Language Parameters

  • Language:

* Control: Dropdown list of supported languages (e.g., English, Spanish, French, German, Japanese, Mandarin).

* Requirement: Must be chosen first, as it influences accent options.

  • Accent (for selected language):

* Control: Dropdown list of available accents (e.g., for English: American (General), British (RP), Australian, Indian, Irish, Scottish, etc.).

* Detail: A "Neutral" option should be available for most languages.

1.4 Voice Quality & Timbre Descriptors

This section leverages natural language processing (NLP) to interpret descriptive keywords.

  • Timbre/Texture Keywords:

* Control: Free-text input field (e.g., "Warm," "Crisp," "Deep," "Breathy," "Resonant," "Smooth," "Gravelly," "Clear," "Mellow," "Bright," "Robotic").

* Limit: Suggest a maximum of 3-5 keywords for optimal results.

* Guidance: Provide examples or a tag cloud of popular descriptors.

  • Vocal Quirks/Characteristics:

* Control: Free-text input field (e.g., "Slight rasp," "Subtle lisp," "Occasional vocal fry," "Husky tone," "Clear articulation").

* Warning: Advise users that overly specific or conflicting quirks may yield unpredictable results.

1.5 Preview & Iteration Controls

  • Text Input for Preview:

* Control: Multi-line text area for users to type or paste sample text (min 10 words, max 200 words).

* Feature: "Suggest Sample Text" button providing diverse examples (e.g., declarative, questioning, emotional).

  • Generate Preview Button:

* Control: Prominently displayed button to synthesize the current voice design with the provided text.

* Feedback: Loading spinner and progress indicator during generation.

  • Playback Controls:

* Control: Standard audio player (Play/Pause, Seek Bar, Volume).

  • Iteration History:

* Control: Option to "Save Snapshot" of a design state and easily revert or compare.

* Feature: A simple "Undo/Redo" for recent parameter changes.

1.6 Output & Management

  • Voice Name:

* Control: Text input field for users to name their custom voice.

* Validation: Required field before saving.

  • Save Voice Button:

* Control: Button to save the designed voice to the user's library.

* Confirmation: Modal confirming successful save and offering options (e.g., "Use Voice Now," "Design Another").

  • Export/API Integration (Advanced):

* Control: Option to generate an API key for the custom voice or download a voice model (if applicable).

* Access: Potentially locked behind higher-tier plans.


2. Wireframe Descriptions

The interface will be split into logical sections, allowing users to progressively refine their voice design.

2.1 Main Voice Designer Interface (Single Page Application - SPA)

  • Layout: Three main columns or sections:

* Left Panel (Voice Attributes & Style - ~30% width):

* Header: "Voice Characteristics"

* Content: Grouped sections for sliders and dropdowns:

* "Core Attributes" (Gender, Age, Pitch, Pace, Volume)

* "Emotional & Style" (Emotional Tendency, Speaking Style, Intonation)

* "Language & Accent" (Language, Accent)

Interaction:* Sliders with clear labels and current values. Dropdowns with searchable options.

* Middle Panel (Timbre & Quirks / Preview Text - ~40% width):

* Header: "Voice Texture & Preview"

* Content:

* "Timbre & Quirks": Free-text input fields with descriptive placeholder text and tooltips for guidance.

* "Preview Text Input": Large text area for sample text, with character count and "Suggest Sample Text" button.

* "Generate Preview" button (prominent, primary action).

* Right Panel (Preview Playback & Iteration - ~30% width):

* Header: "Listen & Refine"

* Content:

* Audio Player: Play/Pause, Seek Bar, Volume control, loading indicator.

* Current Voice Parameters Summary: A read-only display of the most impactful current settings.

* Iteration History/Snapshots: A list of previously generated previews with an option to play them or revert to their settings.

* "Save Voice" button (secondary action, but clearly visible).

2.2 Save Voice Modal

  • Trigger: Clicking "Save Voice" button.
  • Content:

* Header: "Save Your Custom Voice"

* Input Field: "Voice Name" (required, with character limit).

* Optional Description: "Add a short description (optional)."

* Confirmation Message: "Your voice will be saved to your library."

* Buttons: "Cancel," "Save Voice."

  • Post-Save Confirmation:

* Header: "Voice Saved Successfully!"

* Content: "Your voice '[Voice Name]' is now available."

* Buttons: "Go to My Voices," "Design Another Voice," "Use Voice Now (synthesize text)."


3. Color Palettes

A professional, clean, and intuitive color palette will enhance usability and brand perception.

  • Primary Brand Color (e.g., Deep Teal / #00796B): Used for primary action buttons ("Generate Preview"), active states, and key branding elements. Conveys professionalism, innovation, and calm.
  • Secondary Accent Color (e.g., Vibrant Orange / #FFB300): Used for highlighting important information, progress indicators, or secondary calls to action. Provides contrast and draws attention.
  • Neutral Palette:

* Backgrounds (e.g., Light Gray / #F5F5F5): Clean, unobtrusive, provides good contrast for text and controls.

* Card/Container Backgrounds (e.g., White / #FFFFFF): For panels and content blocks, offering clear separation.

* Text (e.g., Dark Gray / #333333): Highly readable for main body text and labels.

* Subtle Text/Icons (e.g., Medium Gray / #757575): For helper text, inactive states, and secondary icons.

  • Feedback Colors:

* Success (e.g., Green / #4CAF50): For successful operations (e.g., "Voice Saved!").

* Error (e.g., Red / #F44336): For warnings or errors (e.g., "Invalid input").

Overall Impression: Modern, professional, inviting, and focused on clarity.


4. UX Recommendations

User experience is paramount for a complex design tool. These recommendations aim to make the process smooth and enjoyable.

  • Real-time Feedback & Responsiveness:

* Sliders should update numerical values instantly as they are dragged.

* Text input fields should have character counts and clear validation messages.

* The "Generate Preview" button should provide clear loading states.

  • Iterative Design Cycle:

* Encourage experimentation by making it easy to generate new previews without committing to a save.

* The "Iteration History" in the right panel is crucial for comparing and reverting.

* Provide a "Reset All" button for starting over.

  • Guidance & Tooltips:

* Each parameter should have a concise tooltip explaining its impact on the voice.

* For free-text fields (Timbre, Quirks), provide examples and suggestions.

* Onboarding tour for first-time users to highlight key features.

  • Progressive Disclosure:

* Start with the most impactful and easily understandable parameters (Gender, Age, Pitch).

* Advanced options or highly specific text inputs can be slightly de-emphasized or placed lower in the hierarchy.

  • Accessibility:

* Ensure high contrast ratios for text and UI elements.

* Provide keyboard navigation support and clear focus states.

* Utilize ARIA labels for screen readers.

  • Performance Optimization:

* Voice generation can be resource-intensive. Optimize backend calls to be efficient.

* Implement smart caching for frequently generated previews or default voice models.

* Provide clear expectations on generation times if they are significant.

  • Save & Resume Functionality:

* Automatically save user's current design progress as a draft, even if they don't explicitly click "Save Voice."

* Allow users to pick up where they left off.

  • Pre-set Voice Templates:

* Offer a library of pre-designed voices (e.g., "Narrator," "Customer Service Bot," "Podcast Host") as starting points.

* Users can select a template and then customize it, reducing initial design friction.

  • Clear Call-to-Actions (CTAs):

* "Generate Preview" should be the most prominent and primary CTA during the design phase.

* "Save Voice" should be clearly distinguishable as the final action.

  • Error Handling:

* Provide user-friendly error messages that explain what went wrong and how to fix it (e.g., "Text too long," "Conflicting voice characteristics detected").

By implementing these detailed specifications and UX recommendations, the AI Voice Designer will offer a powerful, yet approachable, tool for creating custom AI voices.

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
\n\n\n"); 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'\nimport ReactDOM from 'react-dom/client'\nimport App from './App'\nimport './index.css'\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n \n \n \n)\n"); 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'\nimport './App.css'\n\nfunction App(){\n return(\n
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n
\n )\n}\nexport default App\n"); zip.file(folder+"src/index.css","*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#f0f2f5;color:#1a1a2e}\n.app{min-height:100vh;display:flex;flex-direction:column}\n.app-header{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:40px}\nh1{font-size:2.5rem;font-weight:700}\n"); 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)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\n## Open in IDE\nOpen the project folder in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- 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",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "type": "module",\n "scripts": {\n "dev": "vite",\n "build": "vue-tsc -b && vite build",\n "preview": "vite preview"\n },\n "dependencies": {\n "vue": "^3.5.13",\n "vue-router": "^4.4.5",\n "pinia": "^2.3.0",\n "axios": "^1.7.9"\n },\n "devDependencies": {\n "@vitejs/plugin-vue": "^5.2.1",\n "typescript": "~5.7.3",\n "vite": "^6.0.5",\n "vue-tsc": "^2.2.0"\n }\n}\n'); zip.file(folder+"vite.config.ts","import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport { resolve } from 'path'\n\nexport default defineConfig({\n plugins: [vue()],\n resolve: { alias: { '@': resolve(__dirname,'src') } }\n})\n"); zip.file(folder+"tsconfig.json",'{"files":[],"references":[{"path":"./tsconfig.app.json"},{"path":"./tsconfig.node.json"}]}\n'); zip.file(folder+"tsconfig.app.json",'{\n "compilerOptions":{\n "target":"ES2020","useDefineForClassFields":true,"module":"ESNext","lib":["ES2020","DOM","DOM.Iterable"],\n "skipLibCheck":true,"moduleResolution":"bundler","allowImportingTsExtensions":true,\n "isolatedModules":true,"moduleDetection":"force","noEmit":true,"jsxImportSource":"vue",\n "strict":true,"paths":{"@/*":["./src/*"]}\n },\n "include":["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"]\n}\n'); zip.file(folder+"env.d.ts","/// \n"); zip.file(folder+"index.html","\n\n\n \n \n "+slugTitle(pn)+"\n\n\n
\n \n\n\n"); 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'\nimport { createPinia } from 'pinia'\nimport App from './App.vue'\nimport './assets/main.css'\n\nconst app = createApp(App)\napp.use(createPinia())\napp.mount('#app')\n"); var hasApp=Object.keys(extracted).some(function(k){return k.indexOf("App.vue")>=0;}); if(!hasApp) zip.file(folder+"src/App.vue","\n\n\n\n\n"); 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}\n"); 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)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\nOpen in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- 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",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "scripts": {\n "ng": "ng",\n "start": "ng serve",\n "build": "ng build",\n "test": "ng test"\n },\n "dependencies": {\n "@angular/animations": "^19.0.0",\n "@angular/common": "^19.0.0",\n "@angular/compiler": "^19.0.0",\n "@angular/core": "^19.0.0",\n "@angular/forms": "^19.0.0",\n "@angular/platform-browser": "^19.0.0",\n "@angular/platform-browser-dynamic": "^19.0.0",\n "@angular/router": "^19.0.0",\n "rxjs": "~7.8.0",\n "tslib": "^2.3.0",\n "zone.js": "~0.15.0"\n },\n "devDependencies": {\n "@angular-devkit/build-angular": "^19.0.0",\n "@angular/cli": "^19.0.0",\n "@angular/compiler-cli": "^19.0.0",\n "typescript": "~5.6.0"\n }\n}\n'); zip.file(folder+"angular.json",'{\n "$schema": "./node_modules/@angular/cli/lib/config/schema.json",\n "version": 1,\n "newProjectRoot": "projects",\n "projects": {\n "'+pn+'": {\n "projectType": "application",\n "root": "",\n "sourceRoot": "src",\n "prefix": "app",\n "architect": {\n "build": {\n "builder": "@angular-devkit/build-angular:application",\n "options": {\n "outputPath": "dist/'+pn+'",\n "index": "src/index.html",\n "browser": "src/main.ts",\n "tsConfig": "tsconfig.app.json",\n "styles": ["src/styles.css"],\n "scripts": []\n }\n },\n "serve": {"builder":"@angular-devkit/build-angular:dev-server","configurations":{"production":{"buildTarget":"'+pn+':build:production"},"development":{"buildTarget":"'+pn+':build:development"}},"defaultConfiguration":"development"}\n }\n }\n }\n}\n'); zip.file(folder+"tsconfig.json",'{\n "compileOnSave": false,\n "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"]},\n "references":[{"path":"./tsconfig.app.json"}]\n}\n'); zip.file(folder+"tsconfig.app.json",'{\n "extends":"./tsconfig.json",\n "compilerOptions":{"outDir":"./dist/out-tsc","types":[]},\n "files":["src/main.ts"],\n "include":["src/**/*.d.ts"]\n}\n'); zip.file(folder+"src/index.html","\n\n\n \n "+slugTitle(pn)+"\n \n \n \n\n\n \n\n\n"); zip.file(folder+"src/main.ts","import { bootstrapApplication } from '@angular/platform-browser';\nimport { appConfig } from './app/app.config';\nimport { AppComponent } from './app/app.component';\n\nbootstrapApplication(AppComponent, appConfig)\n .catch(err => console.error(err));\n"); zip.file(folder+"src/styles.css","* { margin: 0; padding: 0; box-sizing: border-box; }\nbody { font-family: system-ui, -apple-system, sans-serif; background: #f9fafb; color: #111827; }\n"); 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';\nimport { RouterOutlet } from '@angular/router';\n\n@Component({\n selector: 'app-root',\n standalone: true,\n imports: [RouterOutlet],\n templateUrl: './app.component.html',\n styleUrl: './app.component.css'\n})\nexport class AppComponent {\n title = '"+pn+"';\n}\n"); zip.file(folder+"src/app/app.component.html","
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n \n
\n"); 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}\n"); } zip.file(folder+"src/app/app.config.ts","import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';\nimport { provideRouter } from '@angular/router';\nimport { routes } from './app.routes';\n\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideZoneChangeDetection({ eventCoalescing: true }),\n provideRouter(routes)\n ]\n};\n"); zip.file(folder+"src/app/app.routes.ts","import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n"); 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)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nng serve\n# or: npm start\n\`\`\`\n\n## Build\n\`\`\`bash\nng build\n\`\`\`\n\nOpen in VS Code with Angular Language Service extension.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n.angular/\n"); } /* --- Python --- */ function buildPython(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/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("\n"):"# add dependencies here\n"; zip.file(folder+"main.py",src||"# "+title+"\n# Generated by PantheraHive BOS\n\nprint(title+\" loaded\")\n"); zip.file(folder+"requirements.txt",reqsTxt); zip.file(folder+".env.example","# Environment variables\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\n\`\`\`\n\n## Run\n\`\`\`bash\npython main.py\n\`\`\`\n"); zip.file(folder+".gitignore",".venv/\n__pycache__/\n*.pyc\n.env\n.DS_Store\n"); } /* --- Node.js --- */ function buildNode(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/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)+"\n"; zip.file(folder+"package.json",pkgJson); var fallback="const express=require(\"express\");\nconst app=express();\napp.use(express.json());\n\napp.get(\"/\",(req,res)=>{\n res.json({message:\""+title+" API\"});\n});\n\nconst PORT=process.env.PORT||3000;\napp.listen(PORT,()=>console.log(\"Server on port \"+PORT));\n"; zip.file(folder+"src/index.js",src||fallback); zip.file(folder+".env.example","PORT=3000\n"); zip.file(folder+".gitignore","node_modules/\n.env\n.DS_Store\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\n\`\`\`\n\n## Run\n\`\`\`bash\nnpm run dev\n\`\`\`\n"); } /* --- 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:"\n\n\n\n\n"+title+"\n\n\n\n"+code+"\n\n\n\n"; zip.file(folder+"index.html",indexHtml); zip.file(folder+"style.css","/* "+title+" — styles */\n*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#fff;color:#1a1a2e}\n"); zip.file(folder+"script.js","/* "+title+" — scripts */\n"); zip.file(folder+"assets/.gitkeep",""); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Open\nDouble-click \`index.html\` in your browser.\n\nOr serve locally:\n\`\`\`bash\nnpx serve .\n# or\npython3 -m http.server 3000\n\`\`\`\n"); zip.file(folder+".gitignore",".DS_Store\nnode_modules/\n.env\n"); } /* ===== 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(/\n{2,}/g,"

"); h+="

"+hc+"

Generated by PantheraHive BOS
"; zip.file(folder+app+".html",h); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\nFiles:\n- "+app+".md (Markdown)\n- "+app+".html (styled HTML)\n"); } 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);}});}