Virtual Tour Creator
Run ID: 69cbacc761b1021a29a8b4332026-03-31Real Estate
PantheraHive BOS
BOS Dashboard

360 virtual tour builder with photo stitching, hotspot annotations, room-by-room navigation, and embedded contact forms. Perfect for real estate listings.

Step 1 of 2: AI Image Processing for 360 Virtual Tour Preparation

This document outlines the detailed output for the initial AI Image Processing phase, crucial for preparing your visual assets for a seamless 360-degree virtual tour. This step leverages advanced Artificial Intelligence to analyze, optimize, and enhance your individual photos, ensuring they are perfectly primed for the subsequent 360-degree stitching process.


1. Introduction to AI Image Processing

Welcome to the first critical phase of your Virtual Tour creation! Before any photos can be stitched together into an immersive 360-degree panorama, they undergo a rigorous AI-driven enhancement process. This step is designed to maximize the quality, consistency, and alignment of your individual images, setting the foundation for a flawless virtual experience. Our AI meticulously prepares each photo, correcting imperfections and optimizing parameters to ensure an exceptional end product.


2. Purpose of AI Image Optimization

The primary goal of this AI Image Processing step is to transform your raw input images into a harmonized set of assets, perfectly suited for precise 360-degree stitching. This eliminates common issues such as inconsistent lighting, lens distortions, and misalignments that can lead to visible seams and a less professional virtual tour. By automating these complex adjustments, we ensure superior visual quality and a smooth, immersive user experience.


3. Key AI Image Processing Features & Deliverables

Our AI engine performs a series of sophisticated operations on each of your submitted images:

  • Image Quality Assessment & Enhancement:

* Exposure & Brightness Correction: Automatic adjustment of light levels to ensure consistent exposure across all images, preventing dark or overexposed areas in the final panorama.

* Color Balance & Saturation Optimization: AI-driven color correction to achieve natural and consistent color profiles, making rooms appear vibrant and true-to-life.

* Sharpness & Detail Enhancement: Intelligent sharpening algorithms are applied to bring out fine details without introducing artifacts, improving overall image clarity.

* Noise Reduction: Reduction of digital noise, especially in lower light conditions, to produce cleaner, smoother images.

  • Lens Distortion Correction:

* Geometric Rectification: Automatic detection and correction of barrel or pincushion distortions commonly introduced by wide-angle lenses used for panoramic photography. This ensures straight lines remain straight in the final stitched image.

  • Perspective & Alignment Pre-processing:

* Horizon Leveling: AI analyzes and corrects any tilt or rotation, ensuring all images are perfectly level, which is vital for a seamless horizontal stitch.

* Scale & Aspect Ratio Consistency: Ensures all images are uniformly scaled and maintain consistent aspect ratios, preventing discrepancies during stitching.

  • Seamless Edge Detection & Blending Preparation:

* Feature Point Identification: The AI identifies key visual features within each image, marking them for precise alignment and overlap calculation during the stitching phase.

* Edge Feathering Preparation: Prepares image edges for smooth blending, minimizing visible seams and artifacts in the final 360 panorama.

  • Optional AI-Powered Enhancements (if applicable to your input):

* Minor Object Removal/Cloning: For slight imperfections or unwanted minor objects in the scene (e.g., small cables, dust spots), the AI can intelligently remove them.

* Dynamic Range Optimization (HDR Blending Prep): If multiple exposures are provided for the same viewpoint, the AI will pre-process them for optimal High Dynamic Range (HDR) blending in the next step, capturing details in both shadows and highlights.


4. Input Requirements for Optimal Results

To achieve the best possible outcome from this AI Image Processing step, please ensure your input images adhere to the following guidelines:

  • High Resolution: Provide images with the highest possible resolution from your camera.
  • Consistent Lighting: While AI corrects for inconsistencies, minimizing variations in lighting during capture will yield superior results.
  • Sufficient Overlap: Each photo should ideally overlap with adjacent photos by 25-50% to provide enough data for accurate stitching.
  • Stable Capture: Use a tripod whenever possible to minimize camera shake and ensure consistent viewpoints.
  • Clean Lens: Ensure your camera lens is clean and free of smudges or dust.

5. Output of This Step

Upon completion of the AI Image Processing phase, you will receive a refined set of individual images. These images are not yet stitched into a 360 panorama, but they are now:

  • Optimized for Quality: Enhanced in terms of exposure, color, and sharpness.
  • Geometrically Corrected: Free from lens distortions and perfectly aligned.
  • Ready for Stitching: Each image contains the necessary metadata and visual cues for the subsequent 360-degree stitching algorithm to create a flawless panorama.

This output represents the highest quality individual photo assets, perfectly prepared for the next stage of your virtual tour creation.


6. Next Steps: Proceeding to 360 Photo Stitching

With your images expertly processed by our AI, the system is now poised to move to Step 2: 360 Photo Stitching. In this next phase, these optimized individual images will be seamlessly combined to construct the immersive 360-degree panoramic views for your virtual tour.


7. Action Required

Your optimized image assets are now ready. Please confirm you are ready to proceed to the next step: "Stitch 360 Photos". This will initiate the automated assembly of these individual images into your stunning virtual tour panoramas.

web_builder Output

Virtual Tour Generation Complete: Your Interactive 360 Experience Awaits!

We are delighted to inform you that your professional 360 virtual tour has been successfully generated. This comprehensive tour is designed to captivate your audience, provide an immersive experience, and significantly enhance your property listings or showcased spaces.


1. Your Virtual Tour Link & Dashboard Access

Your unique virtual tour is now live and accessible. You can view, manage, and further customize your tour through your dedicated dashboard.

  • Virtual Tour Preview Link: [Direct Link to Your Generated Virtual Tour]

(Note: This link is unique to your project and will be provided upon completion of the processing phase. Please allow a few moments for full rendering.)*

  • Virtual Tour Management Dashboard: [Link to Your PantheraHive Dashboard]

* From your dashboard, you can edit tour details, add/modify hotspots, update room navigation, review analytics, and access embedding codes.


2. Key Features of Your Generated Virtual Tour

Your virtual tour incorporates a suite of powerful features designed for maximum engagement and utility, especially for real estate professionals.

2.1. Seamless 360 Photo Stitching & Panoramic Views

  • High-Resolution Panoramas: All uploaded 360 images have been expertly stitched to create smooth, high-resolution panoramic views for each designated space.
  • Immersive Experience: Viewers can freely explore each room with 360-degree rotation, offering a realistic sense of presence within the environment.
  • Optimized Loading: The tour is optimized for fast loading times without compromising image quality, ensuring a smooth user experience across various devices and internet speeds.

2.2. Interactive Hotspot Annotations

  • Dynamic Information Points: Strategically placed hotspots allow you to highlight specific features, amenities, or points of interest within each panoramic view.
  • Customizable Content: Each hotspot can contain:

* Text Descriptions: Detailed explanations of features (e.g., "Granite Countertops," "Hardwood Flooring").

* Images: Supplemental photos of specific details (e.g., a close-up of a fixture).

* Videos: Embedded video clips for demonstrations or additional context.

* External Links: Direct links to product pages, floor plans, or external resources.

  • Call-to-Action Integration: Hotspots can also be configured with calls-to-action, such as "Learn More," "View Floor Plan," or "Contact Agent."

2.3. Intuitive Room-by-Room Navigation

  • Logical Flow: The tour provides a clear and intuitive navigation system, allowing viewers to seamlessly move between different rooms and areas of the property.
  • Floor Plan Integration: (If provided) An interactive floor plan overlay helps viewers orient themselves and jump directly to specific rooms.
  • Navigation Hotspots: Dedicated navigation hotspots (e.g., arrows, doors) are placed within each panorama to guide users to adjacent rooms or different levels.
  • Room Selection Menu: A sidebar or dropdown menu lists all available rooms, enabling quick access to any part of the tour.

2.4. Integrated Lead Capture Forms (Contact Forms)

  • Direct Engagement: Embedded contact forms are strategically placed within the tour (e.g., at the end of the tour, or accessible via a dedicated hotspot/button).
  • Customizable Fields: Forms can be customized to capture essential visitor information such as name, email, phone number, and specific inquiries.
  • Automated Notifications: All submitted inquiries will be immediately forwarded to your designated email address, ensuring prompt follow-up.
  • CRM Integration (Optional): Integration options are available to automatically push lead data into your existing CRM system for streamlined management.

2.5. Branding & Customization

  • Your Logo & Branding: Your company logo and branding elements have been integrated into the tour interface for a professional and consistent brand experience.
  • Custom Color Schemes: The tour's visual theme (colors, fonts) can be customized to match your brand guidelines.
  • Agent Information: Dedicated sections for agent photos, contact details, and social media links are included to personalize the viewing experience.

2.6. Mobile Responsiveness & Cross-Browser Compatibility

  • Optimized for All Devices: Your virtual tour is fully responsive, ensuring a flawless viewing experience on desktops, tablets, and smartphones.
  • Wide Browser Support: Compatible with all major web browsers (Chrome, Firefox, Safari, Edge) for maximum accessibility.

3. Real Estate Listing Enhancements

This virtual tour is specifically designed to elevate your real estate listings:

  • Increased Engagement: Virtual tours significantly increase viewer engagement and time spent on listings.
  • Wider Reach: Attracts out-of-town or international buyers by offering a comprehensive remote viewing option.
  • Qualified Leads: Provides a pre-qualifying experience, ensuring that prospective buyers are genuinely interested before scheduling physical showings.
  • Competitive Advantage: Differentiate your listings from competitors by offering a superior and immersive online experience.
  • 24/7 Open House: Your property is always open for viewing, anytime, anywhere.

4. Next Steps & Deployment

Your virtual tour is ready to be shared and deployed across your marketing channels:

  1. Review & Refine: Access your dashboard to review the generated tour. You can easily add, edit, or remove hotspots, adjust navigation, and update contact form details.
  2. Embed on Your Website: Copy the provided embed code from your dashboard and paste it into your property listing page, website, or blog.
  3. Share on Social Media: Use the direct tour link to share on Facebook, Instagram, LinkedIn, and other social platforms to maximize visibility.
  4. Email Marketing: Include the tour link in your email campaigns and newsletters to prospective buyers.
  5. MLS Integration: Most MLS platforms support embedding virtual tour links. Use the provided link to enhance your MLS listing.

5. Support & Resources

Should you have any questions or require further assistance with your virtual tour, please do not hesitate to reach out:

  • Knowledge Base: [Link to Virtual Tour Creator Help Center]
  • Tutorial Videos: [Link to Video Tutorials Playlist]
  • Contact Support: [Link to Support Portal] or reply directly to this email.

Thank you for choosing PantheraHive's Virtual Tour Creator. We are confident that this tool will significantly enhance your marketing efforts and drive superior results.

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