Skip to main content

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

# 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

Step 2: Apply Theme

template_apply_theme → theme: "default"

Step 3: Deploy

content_deploy_site → triggers deploy pipeline
content_deploy_status → check status ("completed" = live)

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

ProblemCauseFix
Deploy returns 500Missing theme templatesApply theme first: POST /templates/apply-theme
Site shows old contentKV cacheRedeploy: POST /deploy
404 on a pagePage not publishedPOST /pages/{id}/publish then redeploy
Custom domain not workingDNS not pointedCNAME to spideriq-tenant-sites.workers.dev
API returns HTML not JSONDomain not configuredAdd X-Content-Domain header
Dynamic page shows "Not Available"Lead not in CRMCheck lead exists: GET /idap/businesses/resolve?place_id=...

Performance

MetricValue
Deploy time2-5 seconds
First byte (cached)~50ms (Cloudflare edge)
First byte (uncached)~200ms (API fetch + Liquid render)
Cache TTL60s pages, 300s docs
Bundle size198KB / 44KB gzipped