Build & Deploy Sites
SpiderIQ sites deploy to Cloudflare's edge network in 2-5 seconds. No npm build, no CI pipeline — just API calls.
Architecture
Your Agent / CLI / Dashboard
│
▼
┌─────────────────────────┐
│ SpiderIQ Content API │ ← Pages, posts, settings, navigation
│ (PostgreSQL storage) │
└──────────┬──────────────┘
│ POST /deploy
▼
┌─────────────────────────┐
│ Deploy Pipeline │ ← Builds _config.json, uploads to KV
│ (2-5 seconds) │
└──────────┬──────────────┘
│
▼
┌─────────────────────────┐
│ Cloudflare Workers │ ← Liquid renderer at the edge
│ (per-client isolation) │ ← Templates from KV
│ │ ← Content from API at request time
└─────────────────────────┘
│
▼
https://yoursite.com
Each client gets an isolated Cloudflare Worker. Templates are stored in per-client KV namespaces. Content is fetched from the API at request time and rendered with LiquidJS.
Deploy Pipeline
Step 1: Create Content
- MCP
- CLI
- cURL
# Use these MCP tools in order:
1. template_get_help → Read the content reference
2. content_create_page → Create pages with blocks
3. content_publish_page → Publish each page
4. content_create_post → Create blog posts (optional)
5. content_publish_post → Publish posts
# Read the reference
spideriq content help --format yaml
# Create a page
spideriq content pages create \
--title "Home" \
--slug "home" \
--template landing \
--blocks '[{"id":"hero-1","type":"hero","data":{"headline":"Welcome"}}]'
# Publish
spideriq content pages publish <page-id>
# Create page
curl -X POST "https://spideriq.ai/api/v1/dashboard/content/pages" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Home",
"slug": "home",
"template": "landing",
"blocks": [{"id":"hero-1","type":"hero","data":{"headline":"Welcome"}}]
}'
# Publish
curl -X POST "https://spideriq.ai/api/v1/dashboard/content/pages/<id>/publish" \
-H "Authorization: Bearer $TOKEN"
Step 2: Apply Theme
- MCP
- CLI
- cURL
template_apply_theme → theme: "default"
spideriq templates apply-theme --theme default
curl -X POST "https://spideriq.ai/api/v1/dashboard/templates/apply-theme" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"theme": "default"}'
Step 3: Deploy
- MCP
- CLI
- cURL
content_deploy_site → triggers deploy pipeline
content_deploy_status → check status ("completed" = live)
spideriq content deploy
spideriq content deploy-status
# Deploy
curl -X POST "https://spideriq.ai/api/v1/dashboard/content/deploy" \
-H "Authorization: Bearer $TOKEN"
# Check status
curl "https://spideriq.ai/api/v1/dashboard/content/deploy/status" \
-H "Authorization: Bearer $TOKEN"
Step 4: Verify
# Check site loads
curl -s -o /dev/null -w "%{http_code}" https://yoursite.com/
# Check a specific page
curl -s -o /dev/null -w "%{http_code}" https://yoursite.com/about
# Check API proxy works (should return JSON, not HTML)
curl -s https://yoursite.com/api/v1/system/health
Custom Domains
Add a Domain
POST /api/v1/dashboard/content/domains
{ "domain": "acme.com" }
Set Up DNS
Point your domain to Cloudflare:
CNAME acme.com → spideriq-tenant-sites.workers.dev
Verify Domain
POST /api/v1/dashboard/content/domains/acme.com/verify
Set as Primary
POST /api/v1/dashboard/content/domains/acme.com/primary
After verification and deploy, your site is live at https://acme.com.
Template Customization
Available Themes
GET /api/v1/dashboard/templates/themes
Currently: default (full-featured starter theme with 29 template files).
Custom Templates
Override any theme template with your own Liquid:
POST /api/v1/dashboard/templates
{
"path": "templates/page.liquid",
"content": "{% layout 'layout/theme.liquid' %}\n{% block content %}\n <h1>{{ page.title }}</h1>\n {{ page.blocks | render_blocks }}\n{% endblock %}"
}
Template Config
Control routes, settings, data sources, and salesperson profiles:
PATCH /api/v1/dashboard/templates/config
{
"theme": "default",
"routes": {
"/pricing": "templates/pricing.liquid"
},
"settings": {
"primary_color": "#2563eb"
},
"data_sources": [
{
"name": "Recent Leads",
"type": "spideriq_job",
"job_id": "uuid-of-completed-job",
"variable_name": "leads_data"
}
],
"salespersons": {
"alex": {
"name": "Alex Chen",
"title": "Account Executive",
"photo_url": "https://...",
"calendar_url": "https://calendly.com/alex"
}
}
}
Deploy History
Track all deployments:
GET /api/v1/dashboard/content/deploy/history
Returns:
deploys:
- id: "uuid"
status: "completed"
version_id: "abc123"
created_at: "2026-04-13T10:30:00Z"
completed_at: "2026-04-13T10:30:03Z"
Content Update Workflow
After the initial deploy, updating content follows the same pattern:
1. Create or update pages/posts
2. Publish new content
3. Deploy again (POST /dashboard/content/deploy)
Each deploy is additive — it includes all published content.
Dynamic Landing Page Deployment
Dynamic landing pages have a special URL pattern but deploy the same way:
# 1. Create page with dynamic_landing template
POST /dashboard/content/pages
{ "template": "dynamic_landing", "slug": "offer", ... }
# 2. Publish
POST /dashboard/content/pages/{id}/publish
# 3. Configure salespersons
PATCH /dashboard/templates/config
{ "salespersons": { "alex": { ... } } }
# 4. Deploy
POST /dashboard/content/deploy
# 5. URLs are now live:
# https://yoursite.com/lp/offer/alex/0x47e66fdad6f1cc73:0x341211b3fccd79e1
The lead data (business name, city, rating, etc.) is fetched from IDAP at request time — no redeploy needed when new leads are added to your CRM.
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| Deploy returns 500 | Missing theme templates | Apply theme first: POST /templates/apply-theme |
| Site shows old content | KV cache | Redeploy: POST /deploy |
| 404 on a page | Page not published | POST /pages/{id}/publish then redeploy |
| Custom domain not working | DNS not pointed | CNAME to spideriq-tenant-sites.workers.dev |
| API returns HTML not JSON | Domain not configured | Add X-Content-Domain header |
| Dynamic page shows "Not Available" | Lead not in CRM | Check lead exists: GET /idap/businesses/resolve?place_id=... |
Performance
| Metric | Value |
|---|---|
| Deploy time | 2-5 seconds |
| First byte (cached) | ~50ms (Cloudflare edge) |
| First byte (uncached) | ~200ms (API fetch + Liquid render) |
| Cache TTL | 60s pages, 300s docs |
| Bundle size | 198KB / 44KB gzipped |