# Getting Started: From Zero to Working SaaS

This guide walks you through taking the skeleton code and turning it into a running service.

## Prerequisites Checklist

- [ ] Domain name with Cloudflare DNS management
- [ ] Mac mini (macOS) with Node.js 22+ and PM2 installed
- [ ] Namecheap hosting account (shared or VPS) with SSH access
- [ ] Stripe account (for billing)
- [ ] Basic familiarity with PHP, Composer, Git
- [ ] Time: ~8-12 hours for initial setup

---

## Phase 1: Backend Setup (Namecheap)

### 1.1 Create Database

In cPanel or Plesk:
- Create MySQL database `wapa_scheduler`
- Create user with full privileges
- Note: DB_HOST (likely `localhost`), DB_NAME, DB_USER, DB_PASSWORD

### 1.2 Upload Backend Files

- Copy the entire `backend/` folder to your hosting. Use FTP/SFTP or Git.
- If using shared hosting without SSH, you can upload as a zip and extract via file manager.

### 1.3 Install Composer Dependencies

If SSH is available:

```bash
cd /path/to/backend
composer install --optimize-autoloader --no-dev
```

If no SSH, you may need to run `composer install` on a local machine with same PHP version, then upload the entire `vendor/` directory. Be careful not to overwrite any existing files.

### 1.4 Configure Environment

- Copy `.env.example` to `.env`
- Edit `.env` with your values:

```
APP_NAME="WAPI Scheduler"
APP_ENV=production
APP_KEY=   # leave blank, will generate
APP_DEBUG=false
APP_URL=https://api.yourdomain.com

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=wapa_scheduler
DB_USERNAME=your_db_user
DB_PASSWORD=your_db_pass

# OpenWA
OPENWA_BASE_URL=https://wa-api.yourdomain.com   # This will be your Cloudflare tunnel to Mac mini
OPENWA_WEBHOOK_SECRET=generate-a-strong-random-string-here

# Stripe
STRIPE_KEY=pk_live_...
STRIPE_SECRET=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...

# Email
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=your_email@gmail.com
MAIL_PASSWORD=your_app_password
MAIL_FROM_ADDRESS=noreply@yourdomain.com
```

- Generate Laravel app key: `php artisan key:generate` (or manually set `APP_KEY=base64:...` later)

### 1.5 Run Migrations

```bash
php artisan migrate --force
```

This creates all tables.

Optional seed: `php artisan db:seed --class=AdminUserSeeder` if you create one.

### 1.6 Set Up Storage

Create the `storage` directories are already there. Ensure `storage/app/public` is writable.

We need to serve QR codes. For simplicity, we can store them in `storage/app/public/qr_codes`. Make a symlink:

```bash
php artisan storage:link
```

On shared hosting, symlink may not be allowed. Instead, you can copy files or serve via route. For now, rely on `storage:link` and ensure it worked: `public/storage` should exist as symlink.

### 1.7 Set Up Cron for Laravel Scheduler

In cPanel → Cron Jobs, add:

```
* * * * * cd /home/username/backend && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1
```

This runs every minute and dispatches health checks and other scheduled jobs.

### 1.8 Create a Queue Worker

Laravel Queues need a worker process to send campaign messages. Use Supervisor if available; otherwise, run a long-lived `php artisan queue:work` in a screen/tmux session or via cron with `--stop-when-empty` (not ideal).

Simpler for MVP: In the same cron above, you could also run `php artisan queue:work --stop-when-empty --tries=1`. But that spawns a new process every minute. Better to use Supervisor.

If Supervisor available, create `/etc/supervisor/conf.d/laravel-worker.conf`:

```
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/username/backend/artisan queue:work database --sleep=3 --tries=3 --timeout=90
autostart=true
autorestart=true
user=username
numprocs=1
redirect_stderr=true
stdout_logfile=/home/username/worker.log
```

Then `supervisorctl reread && supervisorctl update`.

If not, you can manually start: `php artisan queue:work --daemon` (Keep that terminal open or use screen).

### 1.9 Test API Locally

- Visit `https://api.yourdomain.com/api/health` → should return `{"status":"ok"}`.
- Try registering via Postman: `POST /api/auth/register` with JSON body. Should get token.

If you get 404, check that `public/.htaccess` is correct (Laravel default). If 500, check `storage/logs/laravel.log`.

---

## Phase 2: Mac Mini Setup (OpenWA)

### 2.1 Install Node.js and PM2

```bash
# Install Node 22 LTS via Homebrew
brew install node@22

# Link it
brew link --overwrite node@22

# Install PM2 globally
npm install -g pm2
```

### 2.2 Clone and Configure OpenWA

```bash
cd ~
git clone https://github.com/rmyndharis/OpenWA.git
cd OpenWA
npm install
npm run build
```

Create `.env`:

```
SESSION_DIR=~/openwa/sessions
WEBHOOK_URL=https://api.yourdomain.com/webhooks/openwa
WEBHOOK_SECRET=the-same-secret-as-backend-.env
PORT=2785
```

### 2.3 Create Sessions Directory

```bash
mkdir -p ~/openwa/sessions
chmod -R 700 ~/openwa/sessions
```

### 2.4 Start OpenWA with PM2

```bash
pm2 start npm --name "openwa" -- start
pm2 save
pm2 startup  # to auto-start on boot
```

Check logs: `pm2 logs openwa`. Should see some output. It might start without any sessions (empty).

### 2.5 Create Cloudflare Tunnel to OpenWA

We need the backend to reach OpenWA's API. Since OpenWA runs on Mac mini on a non-standard port (2785), we expose it via Cloudflare Tunnel.

On your Mac mini:

```bash
cloudflared tunnel create openwa-api
cloudflared tunnel route dns openwa-api wa-api.yourdomain.com
```

Edit the tunnel config to point to localhost:2785:

```yaml
# ~/.cloudflared/config.yml
tunnel: <tunnel-id>
credentials-file: /Users/yourname/.cloudflared/<tunnel-id>.json

ingress:
  - hostname: wa-api.yourdomain.com
    service: tcp://localhost:2785
  - service: http_status:404
```

Start the tunnel:

```bash
cloudflared service install openwa-api
sudo launchctl load /Library/LaunchDaemons/cloudflared.service.plist
```

Test: `curl https://wa-api.yourdomain.com/api/sessions` (should return something like [] or 401 if auth required).

Now OpenWA API is reachable at that URL. Update `OPENWA_BASE_URL` in backend `.env` accordingly.

---

## Phase 3: Frontend Setup

### 3.1 Install Dependencies and Build

```bash
cd whatsapp-scheduler-saas/frontend
npm install
cp .env.local.example .env.local
# Edit .env.local:
# NEXT_PUBLIC_API_URL=https://api.yourdomain.com
```

Check that `app/src/components/ui/` exists. For shadcn/ui, you need to initialize it. On the frontend directory:

```bash
npx shadcn-ui@latest init
# Choose "default" style, CSS variables: yes, etc.
npx shadcn-ui@latest add button card input label table form dialog dropdown-menu
# etc.
```

Alternatively, for MVP you can use plain Tailwind classes without shadcn components. We'll implement simple forms.

If time is tight, skip shadcn and use basic HTML + Tailwind. We'll provide a minimal UI in upcoming commits.

### 3.2 Deploy to Vercel

```bash
npx vercel --prod
```

Or connect your GitHub repo to Vercel and set environment variables in Vercel dashboard.

After deploy, frontend lives at `https://app.yourdomain.com`.

---

## Phase 4: End-to-End Test

1. Register as a user via frontend.
2. Go to Sessions, click "Add WhatsApp Number".
3. QR code should appear after a few seconds.
4. Scan with your phone.
5. Create a contact (your own number).
6. Create a campaign: text, send now.
7. Check your phone: message received!
8. Verify in dashboard that status shows sent/delivered.

If any step fails, check:

- Backend logs (`storage/logs/laravel.log`)
- OpenWA logs (`pm2 logs openwa`)
- Cloudflare tunnel status
- API response codes (use browser devtools Network tab)

---

## Phase 5: Go Live

1. Switch Stripe keys to live in backend `.env`.
2. Set `APP_ENV=production` and `APP_DEBUG=false`.
3. Open public registration: ensure no maintenance mode.
4. Monitor first few users closely.
5. Set up email notifications (already wired, just configure SMTP).
6. Add Terms of Service and Privacy Policy pages (use templates, include consent).

---

## What I Can Do Next

I can generate:
- The missing Laravel migration files
- The UI components (shadcn-based) for login, dashboard, campaigns
- The admin panel
- Automated test suite
- Docker compose for local development
- More advanced features: recurring campaigns, webhooks, etc.

Let me know which part you want to build first or if you're ready to start testing this skeleton. Once you have the backend and OpenWA talking, we can iterate quickly.

---

## Need Help?

- OpenWA API reference: https://github.com/rmyndharis/OpenWA (check /api/docs)
- Laravel docs: https://laravel.com/docs/11.x
- Next.js: https://nextjs.org/docs

I'm here to debug any issues you encounter. Just paste errors.