A modern, interactive panorama viewer built with Next.js and Marzipano, designed for immersive 360Β° panoramic experiences with seamless navigation between connected scenes.
# Clone the repository
git clone <repository-url>
cd pano-app
# Install dependencies
npm install
# Install Python dependencies
pip install numpy
# Generate panorama configuration
npm run generate-config
# Start development server
npm run dev
Open http://localhost:3000 to view the application.
- Node.js 18.x or later
- Python 3.8 or later
- NumPy for Python (for configuration generation)
# Install Python from python.org or Microsoft Store
python -m pip install numpy
# Using Homebrew
brew install python
python3 -m pip install numpy
# Ubuntu/Debian
sudo apt update
sudo apt install python3 python3-pip
python3 -m pip install numpy
npm run dev
- Start development servernpm run dev:config
- Generate config and start dev servernpm run build
- Build for productionnpm run start
- Start production server
npm run generate-config
- Generate panorama configuration from CSV datanpm run test:config
- Test configuration generation
npm run test
- Run JavaScript/TypeScript testsnpm run test:watch
- Run tests in watch modenpm run test:coverage
- Run tests with coverage reportnpm run test:python
- Run Python configuration testsnpm run test:all
- Run all tests (JS + Python)
npm run lint
- Run ESLintnpm run type-check
- Run TypeScript type checkingnpm run format
- Format code with Prettiernpm run format:check
- Check code formatting
npm run clean
- Remove all build artifacts and temporary files (including standardized tmp directory)
npm run desktop:build:installer
- Build desktop app installer for current platformnpm run desktop:build:unpack
- Build desktop app (unpacked) for current platformnpm run desktop:dev
- Run desktop app in development modenpm run clean:electron
- Clear Electron app data and cache
Cross-Platform Support: The application now supports building for Windows, macOS, and Linux with automatic platform detection for Node.js bundling and file extraction. See for detailed build instructions.
pano-app/
βββ .github/workflows/ # GitHub Actions CI/CD
βββ docs/ # Documentation
β βββ README.md # Setup instructions
β βββ CONFIGURATION.md # Configuration guide
β βββ TROUBLESHOOTING.md # Comprehensive troubleshooting
β βββ FIXES_AND_IMPROVEMENTS.md # Development history
βββ public/ # Static assets
β βββ assets/js/ # Marzipano library
β βββ data/ # CSV data files
β βββ images/ # Panorama images
β βββ config.json # Generated configuration
βββ scripts/ # Build and utility scripts
β βββ node/ # Node.js scripts (recommended)
β βββ generate_marzipano_config.py # Legacy Python script
βββ src/ # Source code
β βββ components/ # React components
β β βββ poi/ # Point of Interest system
β β βββ viewer/ # Panorama viewer components
β β βββ ui/ # UI components
β βββ hooks/ # Custom React hooks
β βββ contexts/ # React contexts
β βββ lib/ # Utility libraries
β βββ pages/ # Next.js pages
β βββ styles/ # CSS modules
β βββ types/ # TypeScript definitions
β βββ utils/ # Utility functions
βββ package.json # Dependencies and scripts
Create a .env.local
file for local development:
# Panorama Configuration
PANORAMA_CONFIG_MODE=standard
PANORAMA_YAW_OFFSET=0
PANORAMA_PITCH_OFFSET=0
PANORAMA_CAMERA_OFFSET=1.2
PANORAMA_MAX_DISTANCE=10.0
PANORAMA_MAX_CONNECTIONS=6
# Development Settings
NEXT_PUBLIC_DEV_MODE=true
NEXT_PUBLIC_SHOW_DEBUG_INFO=false
Place your panorama data in public/data/pano-poses.csv
:
id,x,y,z,qw,qx,qy,qz
pano1,0,0,0,1,0,0,0
pano2,5,0,0,1,0,0,0
id
: Unique panorama identifierx,y,z
: World coordinatesqw,qx,qy,qz
: Quaternion orientation
- Setup: Install dependencies and configure environment
- Data: Add panorama images to
public/images/
- Configuration: Update
public/data/pano-poses.csv
- Generate: Run
npm run generate-config
- Develop: Start with
npm run dev
- Test: Run
npm run test:all
- Build: Create production build with
npm run build
The project includes comprehensive testing:
- Unit Tests: Jest + Testing Library for React components
- Integration Tests: Configuration generation and API endpoints
- Python Tests: Pytest for configuration script validation
- E2E Tests: Lighthouse CI for performance testing
# Run all tests
npm run test:all
# Run specific test suites
npm run test # JavaScript/TypeScript tests
npm run test:python # Python configuration tests
npm run test:coverage # With coverage report
- Connect your repository to Vercel
- Set environment variables in Vercel dashboard
- Deploy automatically on push to main branch
# Build for production
npm run generate-config
npm run build
# Export static files (optional)
npm run export
The application now includes intelligent performance optimizations that automatically adapt based on dataset size:
-
Smart Scene Loading: Progressive quality based on total scene count
- 4-50 scenes: Full quality (4096px max resolution)
- 51-100 scenes: Balanced quality (3072px max resolution)
- 101-200 scenes: Optimized quality (2048px max resolution)
- 200+ scenes: Ultra-light quality (2048px max resolution)
-
Distance-Based Prioritization: Scenes are loaded/unloaded based on spatial proximity
-
Memory Management: Automatic unloading of distant scenes to prevent memory overflow
-
Adaptive Preloading: Intelligent preloading limits based on dataset size
-
Staggered Loading: Prevents system overwhelming with delayed scene loading
A real-time performance monitor is available in the top-right corner showing:
- Number of loaded scenes vs total scenes
- Estimated memory usage
- Average loading times
- Performance status (Excellent/Good/Fair/Poor)
- Manual optimization button
- Image Optimization: Use WebP format for panorama images
- Lazy Loading: Implemented automatically for large datasets
- Caching: Configure appropriate cache headers
- Bundle Analysis: Use
npm run build
to analyze bundle size
- Large Datasets (200+ scenes): Performance is automatically optimized
- Navigation: Move gradually between scenes for best experience
- Browser: Close other tabs if experiencing lag
- Hardware: Ensure graphics drivers are up to date
The interactive minimap includes advanced zoom-based hotspot filtering to reduce visual clutter and improve navigation clarity.
The minimap dynamically adjusts hotspot visibility based on zoom level to prevent overcrowding:
-
100% Zoom: Only distant hotspots are shown (minimum distance of 6.0 units)
- Ideal for overview navigation and identifying major areas
- Reduces clutter in dense scene clusters
-
200% Zoom: More hotspots appear (minimum distance of 3.5 units)
- Balanced view showing moderate detail
- Good for regional navigation
-
300% Zoom: Even closer hotspots become visible (minimum distance of 1.0 units)
- Detailed view for precise navigation
- Shows most scene connections
-
400% Zoom: Nearly all hotspots are visible (minimum distance of 0.5 units)
- Maximum detail view
- All scenes and connections visible
- Zoom: Mouse wheel to zoom in/out (50% - 400%)
- Pan: Click and drag to move around the map
- Reset: Double-click to reset zoom and pan
- Minimize: Click the minimize button to collapse the minimap
- Hotspot Counter: Shows visible/total hotspots (e.g., "π 5/12")
- Zoom Level: Displays current zoom percentage
- Current Scene: Red pulsing dot with direction indicator
- Other Scenes: Green dots for navigable scenes
- Connection Lines: Shows links between visible scenes only
The filtering system uses intelligent proximity detection:
- Distance Calculation: Uses real 3D coordinates for accurate spacing
- Priority System: Always shows current scene and nearby important locations
- Smooth Transitions: Gradual hotspot appearance/disappearance during zoom
- Performance Optimized: Efficient for projects with hundreds of scenes
- Environment variables are properly scoped
- No sensitive data in client-side code
- Regular dependency updates via Dependabot
- Security scanning in CI/CD pipeline
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature
- Make your changes and add tests
- Run tests:
npm run test:all
- Format code:
npm run format
- Commit changes:
git commit -m 'Add amazing feature'
- Push to branch:
git push origin feature/amazing-feature
- Open a Pull Request
- Use TypeScript for type safety
- Follow ESLint and Prettier configurations
- Write tests for new features
- Update documentation as needed
- Setup Guide - Detailed setup instructions
- Configuration Guide - Configuration options
- Troubleshooting - Common issues and solutions
Common issues and solutions:
# Check Python installation
python --version
python3 --version
# Install NumPy
pip install numpy
- Verify images are in
public/images/
- Check file naming matches CSV data
- Ensure proper file permissions
Symptoms: Laggy navigation, slow loading, or high memory usage
Automatic Solutions:
- Smart loading is enabled automatically for large datasets
- Use the Performance Monitor (top-right corner) to check status
- Click "Optimize Performance" button for manual cleanup
Manual Solutions:
- Reduce image file sizes (compress to 80-90% quality)
- Navigate gradually between scenes instead of jumping far distances
- Close other browser tabs to free up memory
- Check browser console for errors
- Update graphics drivers for better WebGL performance
For Large Datasets (100+ scenes):
- Performance optimizations are automatically applied
- Expect 6-16 scenes loaded simultaneously (adaptive)
- Monitor shows performance status and memory usage
For more detailed troubleshooting, see TROUBLESHOOTING.md.
This project is licensed under the MIT License - see the LICENSE file for details.
The panorama viewer includes a comprehensive Point of Interest (POI) system that allows users to create, manage, and interact with points of interest within panoramic scenes. The system is project-specific, meaning each project maintains its own separate POI data.
- Right-click Creation: Create POIs by right-clicking anywhere on the panorama
- Modal Configuration: Configure POI details through an intuitive modal interface
- File Support: Attach images, videos, PDFs, and other files to POIs
- URL Support: Embed external content via iframe URLs (YouTube, Vimeo, and other URLs automatically converted to embeddable format)
- Project-Specific Data: Each project maintains separate POI data
- Data Persistence: POI data is automatically saved and loaded per project
- Interactive Markers: Visual markers show POI locations on the panorama
- Preview System: Click markers to preview POI content
POIComponent.tsx
- Main POI management componentPOIContextMenu.tsx
- Right-click context menu for POI creationPOIModal.tsx
- Modal dialog for POI configurationPOIPreview.tsx
- Preview component for displaying POI contentutils.ts
- Utility functions for coordinate conversion and validation
- Creating a POI: Right-click on any location in the panorama to open the context menu, then select "Create POI"
- Configuring POI: Fill in the POI details in the modal dialog:
- Name (required)
- Description (optional)
- Content type (file upload or URL)
- Content (file or URL)
- Viewing POIs: Click on any POI marker to view its content in a preview modal
POIs are stored with the following structure:
interface POIData {
id: string;
panoramaId: string;
name: string;
description: string;
position: { yaw: number; pitch: number };
type: "file" | "iframe";
content: string;
createdAt: string;
updatedAt: string;
}
GET /api/poi/load?projectId={projectId}&panoramaId={panoramaId}
- Load POIs for a specific project and panoramaPOST /api/poi/save
- Save POI data (requires projectId in request body)POST /api/poi/upload
- Upload POI attachment files (requires projectId in form data)
POI data is stored per project in the following structure:
public/
βββ {projectId}/
β βββ data/
β βββ poi/
β βββ poi-data.json # POI metadata
β βββ attachments/ # Uploaded files
βββ toyota/
β βββ data/
β βββ poi/
β βββ poi-data.json
β βββ attachments/
βββ parking/
βββ data/
βββ poi/
βββ poi-data.json
βββ attachments/
POIs use spherical coordinates:
- Yaw: Horizontal rotation (-180Β° to 180Β°)
- Pitch: Vertical rotation (-90Β° to 90Β°)
The system includes comprehensive error handling for:
- Invalid coordinate ranges
- File upload failures
- Network connectivity issues
- Corrupted data files
- Missing project directories
POI markers use Tailwind CSS classes and can be customized by modifying the component styles.
react-icons/fa
- Font Awesome iconsuuid
- Unique ID generationreact-toastify
- Toast notificationsformidable
- File upload handling
If you encounter any issues or have questions:
- Check the documentation
- Search existing issues
- Create a new issue with detailed information
Happy panorama viewing! π