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

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

AI Voice Designer: Custom Voice Generation - Detailed Professional Output

This document outlines the detailed specifications, user interface design, aesthetic recommendations, and user experience considerations for the "AI Voice Designer" functionality, enabling the creation of completely custom AI voices. The goal is to provide a comprehensive and actionable blueprint for a robust and intuitive voice design platform, leveraging advanced text-to-speech capabilities, specifically with ElevenLabs as the underlying engine.


1. Detailed Voice Design Specifications

The custom AI voice will be defined by a comprehensive set of characteristics, allowing for granular control over its auditory profile. These specifications are grouped into core attributes, vocal qualities, and advanced parameters.

1.1 Core Voice Attributes

  • Gender Identity:

* Options: Male, Female, Non-binary/Androgynous.

* Description: Influences fundamental pitch range and resonance.

  • Age Range:

* Options: Young Adult (18-30), Adult (30-50), Mature Adult (50-70), Senior (70+).

* Description: Affects vocal texture, perceived energy, and slight variations in pitch and timbre.

  • Accent/Dialect:

* Options: Standard American English, British English (RP), Australian English, Indian English, Irish English, Canadian English, Scottish English, etc. (Expand based on ElevenLabs capabilities and target regions).

* Description: Defines pronunciation, intonation patterns, and regional vocal nuances.

  • Language:

* Options: English, Spanish, French, German, Italian, Portuguese, Polish, Hindi, Japanese, Korean, Chinese, Swedish, Norwegian, Danish, Finnish, Russian, Ukrainian, Arabic, Turkish, Czech, Greek, Dutch, Indonesian, Malay, Romanian, Slovak, Thai, Vietnamese. (Dependent on ElevenLabs multi-language support).

* Description: The primary language the voice is designed to speak.

1.2 Vocal Qualities & Personality

  • Pitch:

* Range: Low to High (Fine-tune slider).

* Description: The perceived "height" or "depth" of the voice.

  • Tone:

* Options (Sliders/Multi-choice): Warm/Cool, Bright/Mellow, Clear/Husky, Smooth/Rough.

* Description: The overall emotional color and texture of the voice.

  • Resonance:

* Options (Sliders): Chest/Head (Deep/Light), Nasal/Oral.

* Description: Where the sound vibrations are primarily perceived to originate.

  • Speaking Speed:

* Range: Slow to Fast (Words Per Minute slider).

* Description: The pace at which the voice delivers speech.

  • Loudness/Volume:

* Range: Soft to Loud (Decibel level slider relative to a standard).

* Description: The perceived intensity of the voice.

  • Timbre/Vocal Texture:

* Options (Adjective-based sliders or multi-choice): Breathiness, Mellowness, Sharpness, Richness, Fullness.

* Description: The unique quality of the voice that distinguishes it from others, independent of pitch and loudness.

  • Articulation:

* Options (Sliders): Crisp/Relaxed, Precise/Natural.

* Description: The clarity and distinctness of speech sounds.

  • Emotional Range/Persona:

* Options (Sliders for intensity):

* Calm/Serene: Soothing, composed.

* Energetic/Enthusiastic: Lively, vibrant.

* Authoritative/Confident: Firm, commanding.

* Friendly/Approachable: Warm, inviting.

* Empathetic/Caring: Understanding, compassionate.

* Professional/Formal: Objective, polished.

* Playful/Witty: Lighthearted, humorous.

* Description: The dominant emotional characteristic or personality trait the voice should convey.

1.3 Advanced ElevenLabs Parameters

  • Stability (Consistency):

* Range: 0% to 100% (Slider).

* Description: Dictates how consistent the voice's pitch and tone remain throughout the generated audio. Higher stability can lead to a more monotone delivery, while lower stability allows for more expressiveness and variation.

  • Clarity + Similarity Enhancement (Pronunciation & Uniqueness):

* Range: 0% to 100% (Slider).

* Description: Controls how well the voice pronounces words and maintains its unique characteristics. Higher values improve clarity and make the voice sound more distinct but can sometimes introduce artifacts.

  • Style Exaggeration (Expressiveness):

* Range: 0% to 100% (Slider).

* Description: Amplifies the voice's emotional range and speaking style. Useful for dramatic narration or highly expressive dialogue.

1.4 Use Case Optimization

  • Options: News Reading, Narration (Audiobooks), Customer Service, Gaming Character, Podcast Host, IVR System, Marketing/Advertising, Educational Content, Conversational AI.
  • Description: Pre-tunes certain parameters to suit common applications, providing a good starting point.

2. Wireframe Descriptions (User Interface Design)

The AI Voice Designer will be structured as a multi-step wizard or a single, scrollable page with distinct sections, prioritizing real-time feedback and ease of iteration.

2.1 Overall Layout & Navigation

  • Header: "AI Voice Designer" title, Save/Load Presets, Help/Tutorials.
  • Main Content Area: Divided into logical sections.
  • Side Panel/Footer: Real-time text input for preview, Play/Pause button, Voice Name, "Generate Voice" button.
  • Progress Indicator (if multi-step): Visual representation of current step (e.g., Step 1 of 4).

2.2 Section 1: Basic Information & Starting Point

  • Voice Name (Text Input): [e.g., "PantheraHive Assistant", "Marketing Narrator"]
  • Voice Description (Text Area): [e.g., "A warm, authoritative male voice for corporate communications."]
  • Starting Point:

* Option 1: Start from Scratch (Default selected).

* Option 2: Use a Preset Voice (Dropdown): [e.g., "Standard Male (US)", "Energetic Female (UK)", "Customer Service Bot"]

* Option 3: Load Saved Voice Design (File Upload/Dropdown): For previously designed voices.

  • Use Case Optimization (Dropdown/Radio Buttons): [e.g., News Reading, Narration, Customer Service] - Selecting this pre-populates some initial settings.

2.3 Section 2: Core Attributes

  • Gender Identity (Radio Buttons/Toggle Switch): Male | Female | Androgynous
  • Age Range (Dropdown/Slider with labels): Young Adult | Adult | Mature Adult | Senior
  • Accent/Dialect (Dropdown with Search): [e.g., Standard American, British RP, Australian]
  • Language (Dropdown with Search): [e.g., English, Spanish, French]

2.4 Section 3: Vocal Qualities & Personality

  • Pitch (Slider): Low <---> High (with numerical/descriptive values)
  • Tone (Multiple Sliders):

* Warm <---> Cool

* Bright <---> Mellow

* Clear <---> Husky

* Smooth <---> Rough

  • Resonance (Multiple Sliders):

* Chest <---> Head

* Nasal <---> Oral

  • Speaking Speed (Slider): Slow <---> Fast (with WPM indicator)
  • Loudness/Volume (Slider): Soft <---> Loud (with dB indicator)
  • Timbre/Vocal Texture (Multiple Sliders):

* Breathiness: Low <---> High

* Mellowness: Low <---> High

* Sharpness: Low <---> High

* Richness: Low <---> High

* Fullness: Low <---> High

  • Articulation (Slider): Relaxed <---> Crisp
  • Emotional Range/Persona (Multiple Sliders for intensity):

* Calm: 0% <---> 100%

* Energetic: 0% <---> 100%

* Authoritative: 0% <---> 100%

* Friendly: 0% <---> 100%

* Empathetic: 0% <---> 100%

* Professional: 0% <---> 100%

* Playful: 0% <---> 100%

2.5 Section 4: Advanced Parameters (ElevenLabs Specific)

  • Stability (Slider): 0% <---> 100%
  • Clarity + Similarity Enhancement (Slider): 0% <---> 100%
  • Style Exaggeration (Slider): 0% <---> 100%

2.6 Real-time Preview & Control Panel (Persistent Footer/Side Panel)

  • Text Input Area: [e.g., "Hello, this is a preview of your custom AI voice."]. Max 200-500 characters for quick previews.
  • Play Button (Icon): Initiates audio generation and playback.
  • Stop Button (Icon): Stops playback.
  • Volume Control (Slider): For preview playback, not the voice itself.
  • Voice Name Display: [e.g., "Previewing: PantheraHive Assistant"]
  • "Generate Voice" Button (Primary CTA): Finalizes the voice design and proceeds to the next step (e.g., saving, deploying).
  • "Save Draft" Button (Secondary CTA): Saves current settings without full generation.

3. Color Palettes (UI Aesthetics)

The color palette should be professional, modern, and user-friendly, minimizing eye strain and highlighting interactive elements effectively.

3.1 Option 1: Modern & Professional (Recommended)

  • Primary Brand Color (Accent): #007BFF (Vibrant Blue - for interactive elements, primary buttons, highlights)
  • Secondary Accent: #28A745 (Success Green - for positive feedback, generated voice confirmation)
  • Backgrounds:

* #F8F9FA (Light Grey - main content background)

* #FFFFFF (Pure White - card backgrounds, input fields)

* #E9ECEF (Slightly darker grey - section separators, disabled states)

  • Text Colors:

* #212529 (Dark Grey - primary body text, labels)

* #6C757D (Medium Grey - secondary text, tooltips, descriptions)

* #007BFF (Blue - links)

  • Borders/Dividers: #DEE2E6 (Light Grey)
  • Error/Warning:

* #DC3545 (Red - error messages)

* #FFC107 (Yellow/Orange - warning messages)

3.2 Option 2: Dark Mode Alternative

  • Primary Brand Color (Accent): #66B3FF (Lighter Blue - for interactive elements, primary buttons, highlights)
  • Secondary Accent: #4CAF50 (Green - for positive feedback)
  • Backgrounds:

* #1E1E1E (Dark Grey - main content background)

* #2D2D2D (Slightly lighter dark grey - card backgrounds, input fields)

* #3C3C3C (Medium dark grey - section separators)

  • Text Colors:

* #F0F0F0 (Off-white - primary body text, labels)

* #B0B0B0 (Light Grey - secondary text, tooltips, descriptions)

* #66B3FF (Lighter Blue - links)

  • Borders/Dividers: #4A4A4A (Darker Grey)
  • Error/Warning:

* #FF6B6B (Red - error messages)

* #FFD700 (Gold - warning messages)


4. User Experience (UX) Recommendations

Ensuring an intuitive, efficient, and enjoyable experience is paramount for a complex tool like an AI Voice Designer.

4.1 Iterative Design & Real-time Feedback

  • Instant Preview: Crucial for voice design. Any change to a slider or option should trigger a near-instantaneous re-render of the preview audio when the user clicks "Play."
  • Auditory Cues: Use subtle audio cues for actions like "Play," "Pause," and "Generate."
  • Visual Feedback: Sliders should update numerical values in real-time. Loading indicators for audio generation should be prominent yet unobtrusive.

4.2 Guidance & Education

  • Tooltips/Hover States: Provide concise explanations for each parameter (e.g., "Stability: Controls how consistent the voice's pitch and tone remain...").
  • Contextual Help: Small info icons (i) next to complex parameters that, when clicked, open a modal with more detailed explanations or examples.
  • "What does this sound like?" Examples: For qualitative parameters like "Tone" or "Timbre," offer short audio snippets illustrating different settings.
  • Onboarding Tour: For first-time users, a brief interactive tour highlighting key features and the design flow.

4.3 Ease of Use & Navigation

  • Clear Labeling: All sliders, dropdowns, and buttons should have clear, descriptive labels.
  • Logical Grouping: Parameters should be grouped into intuitive sections (as outlined in the
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);}});}