# ShopCall.ai Deployment Guide
This guide explains how to deploy ShopCall.ai with static hosting and Supabase Edge Functions.
## Architecture Overview
### Current Architecture
- **Frontend**: Static React build (Vite) - Can be hosted on any static hosting provider
- **Backend**: Supabase Edge Functions (Deno runtime)
- **Database**: Supabase PostgreSQL
- **Authentication**: Supabase Auth
## Prerequisites
1. Supabase account and project
2. Static web hosting (Apache, Nginx, Cloudflare Pages, Netlify, etc.)
3. Resend API key for email sending (or alternative email service)
4. Shopify API credentials (if using Shopify integration)
5. Node.js and npm installed locally for building
## Database Setup
The database migrations have already been applied. The following tables were created:
### 1. pending_signups
Stores temporary signup data with OTP for email verification (15-minute expiration).
### 2. oauth_nonces
Stores OAuth state/nonce values for secure OAuth flows (10-minute expiration).
### 3. stores
Stores e-commerce platform credentials and configuration.
## Edge Functions Deployment
### Deployed Edge Functions
1. **auth** - `/functions/v1/auth/*`
- `/auth/signup` - Create new user account with OTP
- `/auth/signup/verify` - Verify OTP and complete registration
- `/auth/signup/resend-otp` - Resend OTP email
- `/auth/login` - Email/password login
- `/auth/logout` - Sign out
- `/auth/check` - Validate session token
2. **shopify-oauth** - `/functions/v1/shopify-oauth/*`
- `/shopify-oauth/init` - Initialize Shopify OAuth flow
- `/shopify-oauth/callback` - Handle Shopify OAuth callback
3. **woocommerce-oauth** - `/functions/v1/woocommerce-oauth/*`
- `/woocommerce-oauth/init` - Initialize WooCommerce OAuth flow
- `/woocommerce-oauth/callback` - Handle WooCommerce callback
4. **shoprenter-oauth** - `/functions/v1/oauth-shoprenter-*`
- `/oauth-shoprenter-init` - Initialize ShopRenter OAuth flow
- `/oauth-shoprenter-callback` - Handle ShopRenter OAuth callback
5. **shoprenter-webhooks** - `/functions/v1/webhook-shoprenter-*`
- `/webhook-shoprenter-uninstall` - Handle ShopRenter app uninstall
6. **shoprenter-api** - `/functions/v1/shoprenter-*`
- `/shoprenter-products/:storeId` - Fetch products from ShopRenter
- `/shoprenter-orders/:storeId` - Fetch orders from ShopRenter
- `/shoprenter-customers/:storeId` - Fetch customers from ShopRenter
- `/shoprenter-sync/:storeId` - Trigger manual data synchronization
7. **shoprenter-scheduled-sync** - `/functions/v1/shoprenter-scheduled-sync`
- Automated background sync for all ShopRenter stores
- Called by pg_cron on schedule (default: hourly)
- Requires `INTERNAL_SYNC_SECRET` header for authentication
8. **gdpr-webhooks** - `/functions/v1/gdpr-webhooks/*`
- `/gdpr-webhooks/customers-data-request` - Handle customer data requests
- `/gdpr-webhooks/customers-redact` - Handle customer data redaction
- `/gdpr-webhooks/shop-redact` - Handle shop data redaction
### Environment Variables for Edge Functions
Configure these in your Supabase project settings:
```bash
# Supabase (automatically available)
SUPABASE_URL=https://YOUR_PROJECT.supabase.co
SUPABASE_ANON_KEY=your_anon_key
# Email Service (Resend)
RESEND_API_KEY=re_YOUR_API_KEY
# Shopify Integration
SHOPIFY_API_KEY=your_shopify_api_key
SHOPIFY_API_SECRET=your_shopify_api_secret
SHOPIFY_REDIRECT_URI=https://YOUR_PROJECT.supabase.co/functions/v1/shopify-oauth/callback
# ShopRenter Integration
SHOPRENTER_CLIENT_ID=your_shoprenter_client_id
SHOPRENTER_CLIENT_SECRET=your_shoprenter_client_secret
# Scheduled Sync Security
INTERNAL_SYNC_SECRET=generate_random_secure_secret_here
# Frontend URL (for OAuth redirects)
FRONTEND_URL=https://yourdomain.com
# Edge Function Base URL
EDGE_FUNCTION_BASE_URL=https://YOUR_PROJECT.supabase.co/functions/v1
# Service Role Key (for admin operations)
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
```
## Frontend Deployment
### Step 1: Configure Environment Variables
Create or update `.env` file in `shopcall.ai-main/`:
```bash
# Supabase Configuration
VITE_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
VITE_SUPABASE_ANON_KEY=your_anon_key
# Backend API Base URL (Supabase Edge Functions)
VITE_API_URL=https://YOUR_PROJECT.supabase.co/functions/v1
# Frontend URL (for OAuth callbacks)
VITE_FRONTEND_URL=https://yourdomain.com
```
### Step 2: Build the Frontend
```bash
cd shopcall.ai-main
npm install
npm run build
```
This creates a `dist/` directory with your static files.
### Step 3: Deploy Static Files
#### Option A: Apache Hosting
1. Upload the contents of `dist/` to your web server (e.g., `/var/www/html/`)
2. Create `.htaccess` file in the root directory for SPA routing:
```apache
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
```
3. Enable `mod_rewrite`:
```bash
sudo a2enmod rewrite
sudo systemctl restart apache2
```
#### Option B: Nginx Hosting
1. Upload the contents of `dist/` to your web server (e.g., `/var/www/shopcall.ai/`)
2. Configure nginx:
```nginx
server {
listen 80;
server_name yourdomain.com;
root /var/www/shopcall.ai;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
```
3. Test and reload:
```bash
sudo nginx -t
sudo systemctl reload nginx
```
#### Option C: Cloudflare Pages / Netlify / Similar
1. Connect your Git repository
2. Set build command: `cd shopcall.ai-main && npm run build`
3. Set publish directory: `shopcall.ai-main/dist`
4. Configure environment variables in the platform's dashboard
## Email Service Setup (Resend)
1. Sign up for [Resend](https://resend.com/)
2. Create an API key
3. Add the API key to your Supabase Edge Function secrets:
```bash
supabase secrets set RESEND_API_KEY=your_api_key
```
4. Verify your sending domain in Resend (recommended for production)
## OAuth Configuration
### Shopify
1. In your Shopify Partner dashboard, update the app settings:
- **App URL**: `https://yourdomain.com`
- **Allowed redirection URL(s)**:
- `https://YOUR_PROJECT.supabase.co/functions/v1/shopify-oauth/callback`
- **GDPR webhooks**:
- Customer data request: `https://YOUR_PROJECT.supabase.co/functions/v1/gdpr-webhooks/customers-data-request`
- Customer data erasure: `https://YOUR_PROJECT.supabase.co/functions/v1/gdpr-webhooks/customers-redact`
- Shop data erasure: `https://YOUR_PROJECT.supabase.co/functions/v1/gdpr-webhooks/shop-redact`
### WooCommerce
No special configuration needed. The OAuth flow is initiated from the dashboard.
### ShopRenter
1. Register your app with ShopRenter by emailing partnersupport@shoprenter.hu with:
- **Application Name**: ShopCall.ai - AI Phone Assistant
- **EntryPoint URL**: `https://yourdomain.com/integrations`
- **RedirectUri URL**: `https://YOUR_PROJECT.supabase.co/functions/v1/oauth-shoprenter-callback`
- **UninstallUri URL**: `https://YOUR_PROJECT.supabase.co/functions/v1/webhook-shoprenter-uninstall`
- **Application Logo**: 250x150px PNG with transparency
- **Required Scopes**: `product:read`, `product:write`, `customer:read`, `customer:write`, `order:read`, `order:write`, `category:read`, `webhook:read`, `webhook:write`
- **Note**: EntryPoint URL should be a static HTTPS endpoint. ShopRenter will call it with authentication parameters, and our backend will redirect with the `sr_install` parameter.
2. Once approved, you'll receive:
- **ClientId** (add to `SHOPRENTER_CLIENT_ID`)
- **ClientSecret** (add to `SHOPRENTER_CLIENT_SECRET`)
3. Test your integration with a ShopRenter test store (request at https://www.shoprenter.hu/tesztigenyles/?devstore=1)
## ShopRenter Scheduled Background Sync Setup
The ShopRenter integration includes automated background synchronization using PostgreSQL's `pg_cron` extension.
### Step 1: Run Database Migration
Execute the scheduled sync migration in your Supabase SQL Editor:
```bash
# Option A: Via Supabase CLI
supabase db push
# Option B: Via Supabase Dashboard
# 1. Go to SQL Editor in Supabase Dashboard
# 2. Create a new query
# 3. Copy contents of supabase/migrations/20250129_shoprenter_scheduled_sync.sql
# 4. Run the query
```
This migration will:
- Enable `pg_cron` and `pg_net` extensions
- Create `sync_logs` table for tracking sync executions
- Create `store_sync_config` table for per-store configuration
- Schedule hourly sync job via pg_cron
- Set up helper functions and views
### Step 2: Configure Database Settings
In Supabase Dashboard, configure the required settings for pg_cron to call Edge Functions:
1. Go to **Project Settings** → **Database** → **Custom Postgres Configuration**
2. Add the following settings:
```
app.internal_sync_secret =
app.supabase_url = https://YOUR_PROJECT.supabase.co
```
**Generate INTERNAL_SYNC_SECRET:**
```bash
# Generate a secure random secret (32 characters)
openssl rand -hex 32
```
### Step 3: Deploy Scheduled Sync Edge Function
Deploy the scheduled sync Edge Function to Supabase:
```bash
supabase functions deploy shoprenter-scheduled-sync
```
### Step 4: Verify Scheduled Job
Check that the pg_cron job is scheduled:
```sql
-- Run in Supabase SQL Editor
SELECT * FROM cron.job WHERE jobname = 'shoprenter-hourly-sync';
```
You should see output like:
```
jobid | schedule | command | nodename | jobname
------+-------------+---------------------------------------------+-----------+-------------------------
1 | 0 * * * * | SELECT trigger_shoprenter_scheduled_sync(); | localhost | shoprenter-hourly-sync
```
### Step 5: Monitor Sync Execution
After the scheduled job runs (at the top of each hour), check the logs:
```sql
-- View recent sync logs
SELECT
id,
sync_type,
platform,
stores_processed,
started_at,
completed_at,
EXTRACT(EPOCH FROM (completed_at - started_at)) as duration_seconds
FROM sync_logs
ORDER BY created_at DESC
LIMIT 10;
-- View sync statistics
SELECT * FROM sync_statistics
ORDER BY sync_date DESC, platform
LIMIT 20;
```
### Step 6: Configure Per-Store Sync Settings
By default, all ShopRenter stores are configured to sync hourly. You can customize:
```sql
-- Disable sync for a specific store
SELECT set_store_sync_enabled('store-uuid-here', false);
-- Change sync frequency (options: '15min', '30min', 'hourly', '6hours', 'daily')
SELECT set_store_sync_frequency('store-uuid-here', '6hours');
-- View all store sync configurations
SELECT
ssc.store_id,
s.store_name,
ssc.enabled,
ssc.sync_frequency,
ssc.last_sync_at,
ssc.next_sync_at,
ssc.sync_products,
ssc.sync_orders,
ssc.sync_customers
FROM store_sync_config ssc
JOIN stores s ON s.id = ssc.store_id
WHERE s.platform_name = 'shoprenter';
```
### Sync Frequency Options
| Frequency | Cron Schedule | Use Case |
|-----------|--------------|----------|
| `15min` | Every 15 minutes | High-frequency stores (limited by API rate limits) |
| `30min` | Every 30 minutes | Active stores with frequent updates |
| `hourly` | Every hour | **Default** - Balanced for most stores |
| `6hours` | Every 6 hours | Low-traffic stores |
| `daily` | Once per day | Archive/backup stores |
### Troubleshooting Scheduled Sync
**Job not running:**
```sql
-- Check if pg_cron extension is enabled
SELECT * FROM pg_extension WHERE extname = 'pg_cron';
-- Check job status
SELECT * FROM cron.job_run_details
WHERE jobid = (SELECT jobid FROM cron.job WHERE jobname = 'shoprenter-hourly-sync')
ORDER BY start_time DESC
LIMIT 10;
```
**Edge Function not being called:**
- Verify `app.internal_sync_secret` and `app.supabase_url` are set in database settings
- Check Edge Function logs in Supabase Dashboard
- Ensure `shoprenter-scheduled-sync` Edge Function is deployed
**Sync failing for specific stores:**
```sql
-- Check sync results for a specific store
SELECT
results->>'store_id' as store_id,
results->>'store_name' as store_name,
results->>'status' as status,
results->>'error_message' as error_message,
results->'products' as products_stats,
results->'orders' as orders_stats,
results->'customers' as customers_stats
FROM sync_logs, jsonb_array_elements(results) as results
WHERE platform = 'shoprenter'
AND results->>'store_id' = 'your-store-uuid'
ORDER BY created_at DESC
LIMIT 5;
```
**Manual trigger for testing:**
```bash
# Manually trigger scheduled sync (for testing)
curl -X POST https://YOUR_PROJECT.supabase.co/functions/v1/shoprenter-scheduled-sync \
-H "x-internal-secret: YOUR_INTERNAL_SYNC_SECRET" \
-H "Content-Type: application/json"
```
### Security Notes
- `INTERNAL_SYNC_SECRET` is required to prevent unauthorized sync triggers
- Only the pg_cron database function has access to this secret
- Sync logs use Row Level Security - users can only see their own store syncs
- Tokens are automatically refreshed when expired
## Testing the Deployment
### 1. Test Authentication
```bash
# Test signup
curl -X POST https://YOUR_PROJECT.supabase.co/functions/v1/auth/signup \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "testpass123",
"full_name": "Test User",
"company_name": "Test Company",
"user_name": "testuser"
}'
# Test login
curl -X POST https://YOUR_PROJECT.supabase.co/functions/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "testpass123"
}'
```
### 2. Test OAuth Flow
1. Navigate to your frontend URL
2. Try connecting a Shopify or WooCommerce store
3. Verify the OAuth callback works correctly
### 3. Test Frontend Routing
1. Navigate to various routes (e.g., `/dashboard`, `/call-logs`)
2. Refresh the page to ensure routing works with static hosting
3. Check browser console for any errors
## Troubleshooting
### Common Issues
**Issue**: 404 errors on routes when refreshing
- **Solution**: Ensure `.htaccess` (Apache) or nginx configuration is properly set up for client-side routing
**Issue**: CORS errors when calling Edge Functions
- **Solution**: Verify CORS headers are set in Edge Functions (`corsHeaders` in each function)
**Issue**: Email not sending
- **Solution**: Check Resend API key is properly configured and verify the email service is active
**Issue**: OAuth callback fails
- **Solution**: Verify redirect URIs match exactly in your OAuth provider settings
## Monitoring and Maintenance
1. **Edge Functions Logs**: Monitor in Supabase Dashboard > Edge Functions > Logs
2. **Database**: Check Supabase Dashboard > Database for any issues
3. **Cleanup**: The database has automatic cleanup for expired records via the functions:
- `delete_expired_pending_signups()`
- `delete_expired_oauth_nonces()`
## Security Considerations
1. **Environment Variables**: Never commit `.env` files to version control
2. **API Keys**: Rotate API keys regularly
3. **HTTPS**: Always use HTTPS in production
4. **Rate Limiting**: Consider adding rate limiting to Edge Functions for production
5. **CORS**: Restrict CORS origins to your actual frontend domain in production
## Support
For issues or questions:
- Check Supabase logs for Edge Function errors
- Review browser console for frontend errors
- Verify environment variables are correctly set