A complete multi-tenant SaaS platform for creating and publishing 360° virtual tours for the real estate sector.
- Multi-Tenant Architecture: Complete tenant isolation with subscription management
- 360° Virtual Tours: Create immersive virtual tours with panoramic images
- Property Management: Manage real estate properties with details and images
- Interactive Hotspots: Navigation, info, and link hotspots within 360° scenes
- Analytics Dashboard: Track tour views and engagement
- Subscription System: Multiple plans with usage limits and quotas
- Public API: REST API for embedding tours on external websites
- Responsive Design: Works on desktop, tablet, and mobile devices
- Custom lightweight MVC framework (no external dependencies)
- Secure authentication with password hashing
- CSRF protection on all forms
- Tenant data isolation at database level
- File upload with validation and security
- Pagination and filtering
- RESTful API with API key authentication
- PHP: 7.0 or higher (compatible up to 8.x)
- MySQL: 5.7 or higher
- Web Server: Apache or Nginx
- PHP Extensions:
- PDO
- pdo_mysql
- gd (for image handling)
- mbstring
- fileinfo
git clone <repository-url> splash360tours
cd splash360toursCopy the environment example file:
cp .env.example .envEdit .env with your database credentials:
DB_HOST=localhost
DB_NAME=splash360tours
DB_USER=root
DB_PASS=your_password
mysql -u root -pCREATE DATABASE splash360tours CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
EXIT;mysql -u root -p splash360tours < database.sqlchmod 755 -R storage/
chmod 755 -R public/Create a virtual host or use .htaccess (already included in public/.htaccess).
Example virtual host:
<VirtualHost *:80>
ServerName splash360.local
DocumentRoot /path/to/splash360tours/public
<Directory /path/to/splash360tours/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/splash360_error.log
CustomLog ${APACHE_LOG_DIR}/splash360_access.log combined
</VirtualHost>Enable mod_rewrite:
sudo a2enmod rewrite
sudo systemctl restart apache2server {
listen 80;
server_name splash360.local;
root /path/to/splash360tours/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}Navigate to: http://localhost or http://splash360.local
The database includes demo data with the following login credentials:
- Email: admin@splash360.com
- Password: password
- Email: john@luxuryrealty.com
- Password: password
- Email: emma@coastalprops.com
- Password: password
- Login to your tenant account
- Create a Property: Go to Properties → Add Property
- Create a Tour: Navigate to the property → Create Tour
- Add Scenes: Upload 360° panoramic images (equirectangular format)
- Add Hotspots: Create interactive hotspots within scenes
- Navigation: Link to another scene
- Info: Display information popup
- Link: Open external URL
- Publish: Set tour status to "Published" and mark as public
- Share: Copy the public URL to share with clients
- Go to Subscription in the main menu
- View current plan and usage statistics
- Change Plan: Select from available plans
- Pay Invoices: Process dummy payments for testing
Include your API key in the request header:
X-API-KEY: your_api_key_here
Find your API key in the tenant settings (platform admin can view all keys).
Health Check
GET /api/health
Response:
{
"success": true,
"message": "API is running",
"version": "1.0.0"
}List Tours
GET /api/tours
Headers: X-API-KEY: your_api_key
Response:
{
"success": true,
"data": [
{
"id": 1,
"title": "Penthouse Virtual Tour",
"slug": "modern-downtown-penthouse-tour",
"description": "Explore every corner...",
"created_at": "2025-01-01 00:00:00"
}
]
}Get Single Tour
GET /api/tours/{slug}
Headers: X-API-KEY: your_api_key
Response:
{
"success": true,
"data": {
"id": 1,
"title": "Penthouse Virtual Tour",
"property_title": "Modern Downtown Penthouse",
"scenes": [
{
"id": 1,
"name": "Living Room",
"image_url": "http://localhost/storage/uploads/scenes/penthouse_living.jpg",
"initial_yaw": 0,
"initial_pitch": 0,
"hotspots": [...]
}
]
}
}splash360tours/
├── app/
│ ├── controllers/ # Application controllers
│ ├── core/ # Core framework classes
│ ├── helpers/ # Helper functions
│ ├── models/ # Data models
│ └── views/ # View templates
├── config/ # Configuration files
├── public/ # Public web root
│ ├── assets/ # CSS, JS, images
│ ├── index.php # Application entry point
│ └── .htaccess # Apache rewrite rules
├── storage/ # File storage
│ └── uploads/ # Uploaded files
├── tests/ # Test files
├── database.sql # Database schema and seed data
├── .env.example # Environment variables template
└── README.md # This file
- Models: Handle database operations and business logic
- Views: Render HTML templates
- Controllers: Process requests and coordinate models/views
- Single database with
tenant_idcolumn in all relevant tables - Automatic tenant filtering in base Model class
- Subscription-based access control with usage limits
- Password hashing using PHP's
password_hash() - CSRF tokens on all forms
- Prepared statements for all SQL queries
- File upload validation (type, size, path traversal prevention)
- Input sanitization and validation
Run functional tests:
php tests/AuthTest.php
php tests/TenantIsolationTest.php
php tests/ApiTest.php- User registration and login
- Property CRUD operations
- Tour creation and publishing
- Scene upload and management
- Hotspot creation and functionality
- Tenant data isolation
- Subscription limit enforcement
- API authentication and endpoints
- 360° viewer basic functionality
- Analytics tracking
-
Environment
- Set
APP_ENV=productionin.env - Set
APP_DEBUG=false - Use strong database credentials
- Set
-
Security
- Enable HTTPS
- Set secure session cookies
- Configure proper file permissions
- Disable PHP error display
-
Performance
- Enable PHP OPcache
- Configure MySQL query cache
- Use CDN for static assets
- Enable GZIP compression
-
Backup
- Regular database backups
- Backup uploaded files in
/storage
-
Monitoring
- Set up error logging
- Monitor disk space for uploads
- Track API usage
- Verify credentials in
.env - Check MySQL service is running
- Ensure database exists
- Enable mod_rewrite (Apache)
- Check
.htaccessfile exists in/public - Verify DocumentRoot points to
/public
- Check
/storage/uploadspermissions (755) - Verify
upload_max_filesizein php.ini - Check available disk space
- Ensure images are equirectangular format
- Check browser console for JavaScript errors
- Verify image paths are accessible
For issues, questions, or contributions, please open an issue on the repository.
MIT License - feel free to use this project for commercial or personal purposes.
Built with PHP, MySQL, and vanilla JavaScript. No external frameworks required.
Splash360 Tours - Making real estate virtual tours accessible to everyone.