A complete, modern appointment booking platform for service-based businesses built with pure PHP and MySQL. Features include multi-tenant architecture, online booking, staff scheduling, calendar management, subscription billing, and REST API.
- ✅ Multi-Tenant Architecture - Single database, isolated tenant data
- ✅ Online Booking - Public booking pages for each business
- ✅ Staff Management - Multiple staff with individual schedules
- ✅ Service Categories - Organize services by category
- ✅ Smart Scheduling - Automatic availability detection with conflict prevention
- ✅ Calendar Views - Day, week, and month views
- ✅ Client Management - Track customer history and bookings
- ✅ Subscription System - Multiple plans with usage limits
- ✅ Billing & Invoicing - Automated billing with payment tracking
- ✅ Email Notifications - Booking confirmations and reminders (simulated)
- ✅ REST API - Availability and booking endpoints
- ✅ File Uploads - Business logos and staff photos
- ✅ Timezone Support - Per-tenant and per-user timezones
- ✅ Security - CSRF protection, password hashing, prepared statements
- PHP 7.0 or higher (compatible with PHP 8.x)
- MySQL 5.7+ or MariaDB 10.2+
- Apache with mod_rewrite (or Nginx with URL rewriting)
- PDO PHP Extension
- Fileinfo PHP Extension
git clone https://github.com/ahmedsaadawi13/splashbook.git
cd splashbookmysql -u root -pCREATE DATABASE splashbook CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
exit;mysql -u root -p splashbook < database.sqlcp .env.example .envEdit .env with your database credentials:
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=splashbook
DB_USERNAME=root
DB_PASSWORD=your_password
chmod -R 755 storage/
chmod -R 755 public/assets/The included .htaccess files should work out of the box. Ensure mod_rewrite is enabled:
sudo a2enmod rewrite
sudo systemctl restart apache2Set your document root to the public/ directory:
<VirtualHost *:80>
ServerName splashbook.local
DocumentRoot /path/to/splashbook/public
<Directory /path/to/splashbook/public>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>server {
listen 80;
server_name splashbook.local;
root /path/to/splashbook/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 $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
}Visit http://splashbook.local (or your configured domain)
- Email: admin@splashbook.example
- Password: password
Bella Beauty Salon (slug: bella-beauty)
- Admin Email: admin@bellasalon.example
- Password: password
- Booking URL: http://splashbook.local/book/bella-beauty
Healthy Smiles Dental (slug: healthy-smiles)
- Admin Email: admin@healthysmiles.example
- Password: password
- Booking URL: http://splashbook.local/book/healthy-smiles
splashbook/
├── app/
│ ├── controllers/ # Request handlers
│ ├── models/ # Database models
│ ├── views/ # HTML templates
│ ├── core/ # Framework classes
│ └── helpers/ # Utility functions
├── bootstrap/
│ └── autoload.php # Autoloader and environment setup
├── config/ # Configuration files
├── public/ # Web root
│ ├── index.php # Entry point
│ ├── assets/ # CSS, JS, images
│ └── .htaccess
├── storage/
│ └── uploads/ # File uploads
├── tests/ # Test scripts
├── database.sql # Database schema
├── .env.example # Environment template
└── README.md
SplashBook provides a REST API for external integrations. All API requests require an API key.
Include your tenant's API key in the request header:
X-API-KEY: your_api_key_here
Find your API key in: Settings → Business Settings → API Key
Get available time slots for booking.
Query Parameters:
service_id(required): Service IDstaff_id(optional): Specific staff member IDdate(optional): Single date (Y-m-d format)date_from(optional): Start of date rangedate_to(optional): End of date range
Example Request:
curl -X GET "http://splashbook.local/api/availability?service_id=1&date=2025-12-01" \
-H "X-API-KEY: bb_live_a1b2c3d4e5f6..."Example Response:
{
"date": "2025-12-01",
"service_id": 1,
"availability": [
{
"staff_id": 1,
"staff_name": "Sarah Johnson",
"slots": [
{
"start_time": "09:00:00",
"end_time": "10:00:00",
"display_time": "9:00 AM"
},
{
"start_time": "10:00:00",
"end_time": "11:00:00",
"display_time": "10:00 AM"
}
]
}
]
}Create a new booking.
Headers:
X-API-KEY: Your API keyContent-Type: application/json
Request Body:
{
"service_id": 1,
"staff_id": 1,
"date": "2025-12-01",
"start_time": "09:00:00",
"client_name": "John Doe",
"client_email": "john@example.com",
"client_phone": "+1-555-0100",
"notes": "First time client"
}Example Request:
curl -X POST "http://splashbook.local/api/booking" \
-H "X-API-KEY: bb_live_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{
"service_id": 1,
"staff_id": 1,
"date": "2025-12-01",
"start_time": "09:00:00",
"client_name": "John Doe",
"client_email": "john@example.com"
}'Example Response:
{
"success": true,
"booking_id": 123,
"reference_number": "BOOK-A1B2C3",
"status": "pending"
}- Navigate to
/register - Fill in business details
- Create admin account
- You'll be automatically logged in with a 14-day trial
- Go to Staff → Add Staff
- Enter staff details
- Set working hours for each day
- Assign services they can provide
- Go to Services
- Create service categories (optional)
- Add services with:
- Name, description
- Duration (in minutes)
- Price
- Color (for calendar)
Share your booking URL: http://yourdomain.com/book/your-business-slug
Clients can:
- Select a service
- Choose date and time
- Enter contact information
- Receive confirmation via email
- View all bookings in Bookings
- Filter by status, date, staff, service
- Update booking status (confirmed, completed, canceled, no-show)
- Add internal notes
- Calendar view shows all scheduled appointments
Three built-in plans (customizable in database):
| Plan | Price/Month | Staff | Services | Bookings/Month |
|---|---|---|---|---|
| Starter | $29 | 3 | 10 | 50 |
| Professional | $79 | 10 | 50 | 300 |
| Enterprise | $199 | 50 | 200 | 2000 |
- CSRF Protection: All forms include CSRF tokens
- Password Hashing: bcrypt hashing for all passwords
- SQL Injection Prevention: PDO prepared statements only
- XSS Prevention: Output escaping in views
- File Upload Validation: Type and size restrictions
- Session Security: HTTP-only cookies, session regeneration
- API Authentication: API key validation
Run basic functional tests:
php tests/run_tests.php- Create model in
app/models/ - Create controller in
app/controllers/ - Add routes in
config/routes.php - Create views in
app/views/
Manual migrations - update database.sql with schema changes.
Currently emails are logged to the email_logs table. To use real SMTP:
- Install PHPMailer or similar
- Update
EmailHelperclass - Configure SMTP settings in
.env
- Check that
mod_rewriteis enabled (Apache) - Verify
.htaccessfiles are present - Check DocumentRoot points to
/public
- Verify credentials in
.env - Check MySQL service is running
- Ensure database exists
- Check permissions on
/storage/uploads - Verify
upload_max_filesizeinphp.ini
- Enable error reporting in
.env:APP_ENV=development - Check PHP error logs
- Verify all required extensions are installed
- Enable OPcache in production
- Add database indexes as needed
- Implement caching layer (Redis/Memcached)
- Use CDN for static assets
- Enable GZIP compression
- Set
APP_ENV=productionin.env - Change default passwords
- Set up SSL certificate (HTTPS)
- Configure email SMTP
- Set up automated backups
- Enable error logging
- Restrict file permissions
- Configure firewall rules
- Set up monitoring
This project is for educational and commercial use.
For issues and questions:
- Open an issue on GitHub
- Check documentation
- Review code comments
Built with ❤️ using pure PHP and MySQL. No frameworks, just clean, beginner-friendly code.