A modern, full-featured SMS campaign management system built with Laravel 12 and React 19. WindSMS enables businesses to create, schedule, and manage SMS marketing campaigns with subscription-based billing and comprehensive analytics.
- Bulk SMS Campaigns: Send SMS to thousands of contacts simultaneously
- Smart Scheduling: Schedule campaigns with enforcement of sending hours (8am - 8pm WAT)
- Recurring Campaigns: Set up daily, weekly, monthly, or custom recurring campaigns
- Spintax Support: Create message variations with AI-powered spintax generation
- Multiple Recipient Types: Send to all contacts, specific tags, or manual phone number lists
- Campaign Analytics: Track sent, failed, and pending messages in real-time
- Contact Database: Store and organize contacts with metadata
- Tag System: Categorize subscribers using tags for targeted campaigns
- Bulk Import: Import contacts via CSV files
- Search & Filter: Quickly find and manage subscribers
- Flexible Plans: Multiple subscription tiers with different SMS allowances
- Paystack Integration: Secure payment processing with automatic webhooks
- Extra SMS Units: Purchase additional SMS credits as needed
- Usage Tracking: Real-time balance monitoring and transaction history
- Auto-renewal: Automatic subscription renewal support
- Custom Sender IDs: Request custom sender IDs for brand recognition
- Admin Approval System: Built-in approval workflow for sender ID requests
- Multiple Sender IDs: Use different sender IDs for different campaigns
- Two-Factor Authentication: Enhanced account security with 2FA
- Queue System: Background processing for large campaigns
- Email Verification: Secure user registration with email verification
- Real-time Logging: Monitor application logs with Laravel Pail
- Dark Mode: User preference-based theme switching
- Responsive Design: Mobile-friendly interface built with Tailwind CSS
- Laravel 12: Modern PHP framework
- Laravel Fortify: Authentication & security
- Laravel Wayfinder: Type-safe routing
- Laravel Soulbscription: Subscription management
- OpenAI PHP: AI-powered message generation
- League CSV: CSV import/export
- SQLite/MySQL: Database support
- React 19: Latest React with React Compiler
- Inertia.js: Modern monolithic SPA architecture
- TypeScript: Type-safe JavaScript
- Tailwind CSS 4: Utility-first CSS framework
- Radix UI: Accessible component primitives
- Lucide Icons: Beautiful icon library
- Recharts: Data visualization
- Vite 7: Lightning-fast build tool
- Laravel Pail: Real-time log monitoring
- Laravel Pint: Opinionated PHP code formatter
- ESLint: JavaScript/React linting
- Prettier: Code formatting
- Concurrently: Run multiple processes simultaneously
- PHP 8.2 or higher
- Composer
- Node.js 18 or higher
- NPM or Yarn
- SQLite or MySQL database
The easiest way to set up the project is using the automated setup script:
composer run setupThis will:
- Install PHP dependencies
- Create
.envfile from.env.example - Generate application key
- Run database migrations
- Install Node dependencies
- Build frontend assets
If you prefer manual setup:
Clone the repository
git clone <repository-url>cd windsms
Install PHP dependencies
composer install
Environment configuration
cp .env.example .env php artisan key:generate
Configure database
For SQLite (default):
touch database/database.sqlite
For MySQL, update
.env:DB_CONNECTION=mysqlDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=windsmsDB_USERNAME=rootDB_PASSWORD=
Run migrations
php artisan migrate
Seed the database (optional)
php artisan db:seed
This creates a test user:
- Email: test@example.com
- Password: password
Install Node dependencies
npm install
Build frontend assets
npm run build
The application includes a convenient development script that runs all necessary services:
composer run devThis starts:
- Laravel server on http://127.0.0.1:8000
- Queue worker for background jobs
- Laravel Pail for real-time logs
- Vite dev server with HMR on http://localhost:5173
You can also run services individually:
# Laravel server
php artisan serve
# Queue worker (required for campaigns)
php artisan queue:work --tries=3
# Watch logs
php artisan pail
# Vite dev server
npm run dev# Build assets for production
npm run build
# Serve with production server
php artisan serveFor SSR support:
composer run dev:ssrConfigure your SMS provider in .env:
# Add your SMS provider credentials# Example for SMS Live247SMSLIVE247_API_TOKEN=your_token_hereSMSLIVE247_SENDER_ID=YourBrandPAYSTACK_PUBLIC_KEY=your_public_keyPAYSTACK_SECRET_KEY=your_secret_keyPAYSTACK_PAYMENT_URL=https://api.paystack.coPAYSTACK_MERCHANT_EMAIL=your@email.comOPENAI_API_KEY=your_openai_api_keyMAIL_MAILER=smtpMAIL_HOST=your_smtp_hostMAIL_PORT=587MAIL_USERNAME=your_usernameMAIL_PASSWORD=your_passwordMAIL_FROM_ADDRESS=noreply@yourdomain.comMAIL_FROM_NAME="${APP_NAME}"For production, use a more robust queue driver:
QUEUE_CONNECTION=redis# orQUEUE_CONNECTION=database- Creation: User creates campaign with recipients and message
- Validation: System checks SMS balance and subscription status
- Scheduling: Campaign scheduled for immediate or future dispatch
- Processing: Queue workers send SMS in batches
- Tracking: Real-time updates on delivery status
- Completion: Final stats recorded with success/failure counts
The system automatically calculates SMS units:
- Standard SMS: 160 characters = 1 unit
- Extended SMS: 161-306 chars = 2 units, 307-459 chars = 3 units, etc.
- Unicode (with special characters): 70 chars = 1 unit
The application uses feature-based subscriptions:
- Each plan includes SMS units
- Units are consumed when campaigns are sent
- Users can purchase extra units
- Expired subscriptions prevent campaign sending
# Run PHPUnit tests
composer run test# Or directly
php artisan test# Format PHP code
./vendor/bin/pint# Lint and fix
npm run lint
# Format code
npm run format
# Check formatting
npm run format:checkwindsms/
├── app/
│ ├── Http/
│ │ ├── Controllers/ # Request handlers
│ │ ├── Middleware/ # HTTP middleware
│ │ └── Requests/ # Form request validation
│ ├── Jobs/ # Queue jobs
│ ├── Models/ # Eloquent models
│ ├── Services/ # Business logic
│ └── Shared/
│ └── Enums/ # Application enums
├── database/
│ ├── migrations/ # Database migrations
│ └── seeders/ # Database seeders
├── resources/
│ ├── css/ # Stylesheets
│ └── js/
│ ├── components/ # React components
│ ├── layouts/ # Page layouts
│ ├── pages/ # Inertia pages
│ └── routes/ # Wayfinder routes
├── routes/
│ ├── web.php # Web routes
│ └── settings.php # Settings routes
└── public/ # Public assets
The application includes scheduled commands for:
# Process recurring campaigns
php artisan campaigns:recurring
# Reprocess pending SMS
php artisan sms:reprocess-pendingAdd to your crontab:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
If you encounter process timeout errors with the queue worker:
# Use queue:work instead of queue:listen
php artisan queue:work --timeout=300 --tries=3Or increase the timeout in your configuration.
If you see errors about missing TypeScript route files, regenerate them:
npm run devThe Wayfinder plugin will automatically generate route definitions.
For SQLite, ensure the database file exists:
touch database/database.sqlite
chmod 664 database/database.sqlite- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is open-sourced software licensed under the MIT license.
- Laravel - The PHP Framework
- React - JavaScript Library
- Inertia.js - Modern Monolith
- Tailwind CSS - CSS Framework
- Radix UI - UI Components
- Shadcn/ui - Component Design
For support, email dlktimothy@gmail.com or open an issue in the repository.
- Documentation - Coming soon
- API Documentation - Coming soon
- Changelog - Coming soon
Built with ❤️ Timadey