temproary docs uplaoded
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,860 @@
|
||||
import { useState } from "react";
|
||||
|
||||
const Section = ({ title, children, defaultOpen = false }) => {
|
||||
const [open, setOpen] = useState(defaultOpen);
|
||||
return (
|
||||
<div className="mb-4 border border-gray-200 rounded-xl overflow-hidden">
|
||||
<button
|
||||
onClick={() => setOpen(!open)}
|
||||
className="w-full flex items-center justify-between p-4 bg-gray-50 hover:bg-gray-100 transition-colors"
|
||||
>
|
||||
<span className="text-lg font-bold text-gray-900">{title}</span>
|
||||
<span className="text-xl text-gray-500">{open ? "−" : "+"}</span>
|
||||
</button>
|
||||
{open && <div className="p-5 bg-white">{children}</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Badge = ({ color, children }) => {
|
||||
const colors = {
|
||||
blue: "bg-blue-100 text-blue-800",
|
||||
green: "bg-green-100 text-green-800",
|
||||
purple: "bg-purple-100 text-purple-800",
|
||||
orange: "bg-orange-100 text-orange-800",
|
||||
red: "bg-red-100 text-red-800",
|
||||
gray: "bg-gray-100 text-gray-800",
|
||||
teal: "bg-teal-100 text-teal-800",
|
||||
};
|
||||
return (
|
||||
<span className={`px-2 py-0.5 rounded-full text-xs font-semibold ${colors[color]}`}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const ServerBox = ({ title, subtitle, color, children }) => {
|
||||
const borderColors = {
|
||||
blue: "border-blue-400 bg-blue-50",
|
||||
purple: "border-purple-400 bg-purple-50",
|
||||
green: "border-green-400 bg-green-50",
|
||||
};
|
||||
return (
|
||||
<div className={`border-2 rounded-xl p-4 ${borderColors[color]}`}>
|
||||
<h3 className="font-bold text-lg mb-1">{title}</h3>
|
||||
<p className="text-xs text-gray-500 mb-3">{subtitle}</p>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const AppBlock = ({ name, purpose, port, badge }) => (
|
||||
<div className="flex items-center gap-2 p-2 bg-white rounded-lg border border-gray-200 mb-2">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-semibold text-sm">{name}</span>
|
||||
{badge && <Badge color={badge.color}>{badge.text}</Badge>}
|
||||
</div>
|
||||
<p className="text-xs text-gray-500">{purpose}</p>
|
||||
</div>
|
||||
{port && <span className="text-xs font-mono text-gray-400">:{port}</span>}
|
||||
</div>
|
||||
);
|
||||
|
||||
const CostRow = ({ item, monthly, notes }) => (
|
||||
<div className="flex items-center justify-between py-2 border-b border-gray-100">
|
||||
<div>
|
||||
<span className="font-medium text-sm">{item}</span>
|
||||
{notes && <p className="text-xs text-gray-400">{notes}</p>}
|
||||
</div>
|
||||
<span className="font-bold text-sm">{monthly}</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
const Step = ({ num, title, code }) => (
|
||||
<div className="mb-4">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<span className="w-6 h-6 rounded-full bg-gray-900 text-white text-xs flex items-center justify-center font-bold">
|
||||
{num}
|
||||
</span>
|
||||
<span className="font-semibold text-sm">{title}</span>
|
||||
</div>
|
||||
{code && (
|
||||
<pre className="bg-gray-900 text-green-400 text-xs p-3 rounded-lg overflow-x-auto whitespace-pre-wrap">
|
||||
{code}
|
||||
</pre>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
const Arrow = ({ label }) => (
|
||||
<div className="flex flex-col items-center py-2">
|
||||
<span className="text-xs text-gray-500 mb-1">{label}</span>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" className="text-gray-400">
|
||||
<path d="M12 4v16m0 0l-4-4m4 4l4-4" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default function Architecture() {
|
||||
const [tab, setTab] = useState("overview");
|
||||
|
||||
const tabs = [
|
||||
{ id: "overview", label: "Architecture" },
|
||||
{ id: "hostinger", label: "Hostinger VPS" },
|
||||
{ id: "vastai", label: "Vast.ai GPU" },
|
||||
{ id: "models", label: "AI Models" },
|
||||
{ id: "setup", label: "Setup Guide" },
|
||||
{ id: "costs", label: "Costs" },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white p-4 max-w-4xl mx-auto">
|
||||
<div className="mb-6">
|
||||
<h1 className="text-2xl font-black text-gray-900">IGNY8 Self-Hosted AI Infrastructure</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">Hostinger VPS + Vast.ai GPU — Zero API Costs Architecture</p>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-1 mb-6 overflow-x-auto pb-2">
|
||||
{tabs.map((t) => (
|
||||
<button
|
||||
key={t.id}
|
||||
onClick={() => setTab(t.id)}
|
||||
className={`px-3 py-1.5 rounded-lg text-xs font-semibold whitespace-nowrap transition-colors ${
|
||||
tab === t.id ? "bg-gray-900 text-white" : "bg-gray-100 text-gray-600 hover:bg-gray-200"
|
||||
}`}
|
||||
>
|
||||
{t.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{tab === "overview" && (
|
||||
<div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
|
||||
<ServerBox title="Hostinger VPS" subtitle="CPU-only • Web + AI Orchestration" color="blue">
|
||||
<AppBlock name="Plesk" purpose="Web hosting panel — client sites, IGNY8 frontend" port="8443" />
|
||||
<AppBlock name="Flowise" purpose="AI workflow builder — RAG chatbots, content pipelines" port="3000" badge={{ color: "green", text: "IGNY8 Core" }} />
|
||||
<AppBlock name="Open WebUI" purpose="ChatGPT-like interface for clients" port="3001" badge={{ color: "blue", text: "Client-facing" }} />
|
||||
<AppBlock name="Chroma" purpose="Vector database for RAG / knowledge bases" port="8000" />
|
||||
<AppBlock name="LiteLLM" purpose="API gateway — routes to Vast.ai GPU" port="4000" badge={{ color: "purple", text: "Bridge" }} />
|
||||
<AppBlock name="Nginx" purpose="Reverse proxy + SSL for all services" port="443" />
|
||||
</ServerBox>
|
||||
|
||||
<ServerBox title="Vast.ai GPU Server" subtitle="2x RTX 3090 (48GB) • AI Inference" color="purple">
|
||||
<AppBlock name="Ollama" purpose="LLM inference engine" port="11434" badge={{ color: "orange", text: "GPU" }} />
|
||||
<AppBlock name="Qwen3 32B" purpose="Content writing for IGNY8" badge={{ color: "green", text: "Text Gen" }} />
|
||||
<AppBlock name="Qwen3 30B-A3B" purpose="Fast inference for chat / SEO tasks" badge={{ color: "green", text: "Text Gen" }} />
|
||||
<AppBlock name="FLUX.1 / SD 3.5" purpose="Image generation via ComfyUI" port="8188" badge={{ color: "teal", text: "Image Gen" }} />
|
||||
<AppBlock name="Wan 2.1 / LTX-Video" purpose="Video generation via ComfyUI" badge={{ color: "red", text: "Video Gen" }} />
|
||||
<AppBlock name="ComfyUI" purpose="Unified UI for image + video generation" port="8188" />
|
||||
</ServerBox>
|
||||
</div>
|
||||
|
||||
<div className="bg-gray-50 rounded-xl p-4 mb-4">
|
||||
<h3 className="font-bold text-sm mb-3">How They Connect</h3>
|
||||
<div className="space-y-2 text-xs">
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge color="blue">Hostinger</Badge>
|
||||
<span className="text-gray-400">→ LiteLLM proxy →</span>
|
||||
<Badge color="purple">Vast.ai Ollama</Badge>
|
||||
<span className="text-gray-500">Text generation (OpenAI-compatible API)</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge color="blue">Flowise</Badge>
|
||||
<span className="text-gray-400">→ LiteLLM →</span>
|
||||
<Badge color="purple">Qwen3 models</Badge>
|
||||
<span className="text-gray-500">IGNY8 content writing pipeline</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge color="blue">IGNY8 App</Badge>
|
||||
<span className="text-gray-400">→ HTTP API →</span>
|
||||
<Badge color="purple">ComfyUI</Badge>
|
||||
<span className="text-gray-500">Image/video generation requests</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge color="blue">Open WebUI</Badge>
|
||||
<span className="text-gray-400">→ Ollama API →</span>
|
||||
<Badge color="purple">Any loaded model</Badge>
|
||||
<span className="text-gray-500">Client chat interface</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-green-50 border border-green-200 rounded-xl p-4">
|
||||
<h3 className="font-bold text-sm text-green-800 mb-2">Zero API Cost Model</h3>
|
||||
<div className="text-xs text-green-700 space-y-1">
|
||||
<p>• All LLM inference runs on your own GPU — no OpenAI/Anthropic API charges</p>
|
||||
<p>• Image generation uses open-source FLUX.1/SD 3.5 — no Midjourney/DALL-E costs</p>
|
||||
<p>• Video generation uses Wan 2.1/LTX-Video — no Runway/Sora costs</p>
|
||||
<p>• Only fixed costs: Hostinger VPS (~$12-25/mo) + Vast.ai GPU (~$200/mo)</p>
|
||||
<p>• Total: ~$215-225/month for unlimited AI generation</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tab === "hostinger" && (
|
||||
<div>
|
||||
<Section title="Recommended VPS Plan" defaultOpen={true}>
|
||||
<div className="space-y-3">
|
||||
<div className="bg-blue-50 p-3 rounded-lg">
|
||||
<p className="font-bold text-sm">KVM 4 or higher recommended</p>
|
||||
<p className="text-xs text-gray-600 mt-1">4 vCPU, 16GB RAM, 200GB NVMe — handles Plesk + all CPU services comfortably</p>
|
||||
</div>
|
||||
<div className="text-sm space-y-2">
|
||||
<p className="font-semibold">What runs on Hostinger (CPU-only):</p>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="bg-white p-2 rounded border"><span className="font-mono text-xs">Plesk</span> — Web hosting panel</div>
|
||||
<div className="bg-white p-2 rounded border"><span className="font-mono text-xs">Flowise</span> — AI workflow engine</div>
|
||||
<div className="bg-white p-2 rounded border"><span className="font-mono text-xs">Open WebUI</span> — Chat interface</div>
|
||||
<div className="bg-white p-2 rounded border"><span className="font-mono text-xs">Chroma</span> — Vector DB</div>
|
||||
<div className="bg-white p-2 rounded border"><span className="font-mono text-xs">LiteLLM</span> — API proxy</div>
|
||||
<div className="bg-white p-2 rounded border"><span className="font-mono text-xs">Nginx</span> — Reverse proxy</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 bg-yellow-50 p-3 rounded-lg">
|
||||
<strong>Important:</strong> Don't install Ollama on Hostinger — it will be too slow on CPU. All AI inference goes through LiteLLM → Vast.ai GPU server.
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="Docker Compose Stack">
|
||||
<pre className="bg-gray-900 text-green-400 text-xs p-4 rounded-lg overflow-x-auto whitespace-pre-wrap">{`# docker-compose.yml on Hostinger VPS
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
flowise:
|
||||
image: flowiseai/flowise
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- flowise_data:/root/.flowise
|
||||
environment:
|
||||
- FLOWISE_USERNAME=admin
|
||||
- FLOWISE_PASSWORD=your_secure_password
|
||||
restart: always
|
||||
|
||||
chromadb:
|
||||
image: chromadb/chroma
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
- chroma_data:/chroma/chroma
|
||||
restart: always
|
||||
|
||||
litellm:
|
||||
image: ghcr.io/berriai/litellm:main-latest
|
||||
ports:
|
||||
- "4000:4000"
|
||||
volumes:
|
||||
- ./litellm_config.yaml:/app/config.yaml
|
||||
command: ["--config", "/app/config.yaml"]
|
||||
restart: always
|
||||
|
||||
open-webui:
|
||||
image: ghcr.io/open-webui/open-webui:main
|
||||
ports:
|
||||
- "3001:8080"
|
||||
environment:
|
||||
# Point to Vast.ai Ollama (via SSH tunnel)
|
||||
- OLLAMA_BASE_URL=http://litellm:4000
|
||||
volumes:
|
||||
- openwebui_data:/app/backend/data
|
||||
restart: always
|
||||
|
||||
volumes:
|
||||
flowise_data:
|
||||
chroma_data:
|
||||
openwebui_data:`}</pre>
|
||||
</Section>
|
||||
|
||||
<Section title="LiteLLM Config (Bridge to Vast.ai)">
|
||||
<pre className="bg-gray-900 text-green-400 text-xs p-4 rounded-lg overflow-x-auto whitespace-pre-wrap">{`# litellm_config.yaml
|
||||
# Routes all AI requests to your Vast.ai GPU server
|
||||
|
||||
model_list:
|
||||
- model_name: qwen3-32b
|
||||
litellm_params:
|
||||
model: ollama/qwen3:32b
|
||||
api_base: http://VAST_AI_IP:11434
|
||||
|
||||
- model_name: qwen3-30b-moe
|
||||
litellm_params:
|
||||
model: ollama/qwen3:30b-a3b
|
||||
api_base: http://VAST_AI_IP:11434
|
||||
|
||||
- model_name: qwen3-14b
|
||||
litellm_params:
|
||||
model: ollama/qwen3:14b
|
||||
api_base: http://VAST_AI_IP:11434
|
||||
|
||||
- model_name: qwen3-8b
|
||||
litellm_params:
|
||||
model: ollama/qwen3:8b
|
||||
api_base: http://VAST_AI_IP:11434
|
||||
|
||||
general_settings:
|
||||
master_key: sk-your-master-key-here`}</pre>
|
||||
<div className="mt-3 text-xs text-gray-500 bg-orange-50 p-3 rounded-lg">
|
||||
<strong>Security:</strong> Use SSH tunnel or WireGuard VPN between Hostinger and Vast.ai. Never expose Ollama port directly to the internet.
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="Nginx Reverse Proxy">
|
||||
<pre className="bg-gray-900 text-green-400 text-xs p-4 rounded-lg overflow-x-auto whitespace-pre-wrap">{`# /etc/nginx/sites-available/ai-services
|
||||
|
||||
# Flowise — IGNY8 AI workflows
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name flowise.yourdomain.com;
|
||||
ssl_certificate /etc/letsencrypt/live/...;
|
||||
location / {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
}
|
||||
|
||||
# Open WebUI — Client chat
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name chat.yourdomain.com;
|
||||
ssl_certificate /etc/letsencrypt/live/...;
|
||||
location / {
|
||||
proxy_pass http://localhost:3001;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
}
|
||||
|
||||
# LiteLLM — API endpoint
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name api.yourdomain.com;
|
||||
ssl_certificate /etc/letsencrypt/live/...;
|
||||
location / {
|
||||
proxy_pass http://localhost:4000;
|
||||
}
|
||||
}`}</pre>
|
||||
</Section>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tab === "vastai" && (
|
||||
<div>
|
||||
<Section title="Server Spec: m:49870" defaultOpen={true}>
|
||||
<div className="grid grid-cols-2 gap-3 mb-4">
|
||||
<div className="bg-purple-50 p-3 rounded-lg">
|
||||
<p className="text-xs text-gray-500">GPU</p>
|
||||
<p className="font-bold">2x RTX 3090 (48GB total)</p>
|
||||
</div>
|
||||
<div className="bg-purple-50 p-3 rounded-lg">
|
||||
<p className="text-xs text-gray-500">CPU</p>
|
||||
<p className="font-bold">AMD EPYC 7543 (13.5/128 cores)</p>
|
||||
</div>
|
||||
<div className="bg-purple-50 p-3 rounded-lg">
|
||||
<p className="text-xs text-gray-500">RAM</p>
|
||||
<p className="font-bold">54GB / 516GB</p>
|
||||
</div>
|
||||
<div className="bg-purple-50 p-3 rounded-lg">
|
||||
<p className="text-xs text-gray-500">Storage</p>
|
||||
<p className="font-bold">442GB NVMe</p>
|
||||
</div>
|
||||
<div className="bg-purple-50 p-3 rounded-lg">
|
||||
<p className="text-xs text-gray-500">Location</p>
|
||||
<p className="font-bold">Bulgaria</p>
|
||||
</div>
|
||||
<div className="bg-purple-50 p-3 rounded-lg">
|
||||
<p className="text-xs text-gray-500">Cost</p>
|
||||
<p className="font-bold">$0.277/hr (~$200/mo)</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-yellow-50 border border-yellow-200 p-3 rounded-lg text-xs">
|
||||
<strong>Note:</strong> 97.2% reliability = ~20hrs downtime/month. For production, consider m:24191 (Czechia, 99.38% reliability, $0.288/hr) or set up auto-failback to a paid API in LiteLLM config.
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="What Runs on Vast.ai GPU">
|
||||
<div className="space-y-3">
|
||||
<div className="bg-white border-2 border-green-300 rounded-lg p-3">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Badge color="green">Text Gen</Badge>
|
||||
<span className="font-bold text-sm">Ollama + Qwen3 Models</span>
|
||||
</div>
|
||||
<p className="text-xs text-gray-600">IGNY8 content writing, SEO content, chat responses</p>
|
||||
<div className="mt-2 text-xs space-y-1">
|
||||
<p>• Qwen3 32B (dense) — ~20GB VRAM, best quality</p>
|
||||
<p>• Qwen3 30B-A3B (MoE) — ~19GB VRAM, fastest</p>
|
||||
<p>• Qwen3 14B — ~9GB VRAM, for concurrent tasks</p>
|
||||
<p>• Load models on demand via Ollama</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white border-2 border-teal-300 rounded-lg p-3">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Badge color="teal">Image Gen</Badge>
|
||||
<span className="font-bold text-sm">ComfyUI + FLUX.1 / Stable Diffusion</span>
|
||||
</div>
|
||||
<p className="text-xs text-gray-600">Blog images, social media graphics, product visuals for IGNY8</p>
|
||||
<div className="mt-2 text-xs space-y-1">
|
||||
<p>• FLUX.1 [dev] — best quality, ~12GB VRAM</p>
|
||||
<p>• Stable Diffusion 3.5 — wide ecosystem, ~8GB VRAM</p>
|
||||
<p>• SDXL-Lightning — fast generation, ~6GB VRAM</p>
|
||||
<p>• All via ComfyUI API (port 8188)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white border-2 border-red-300 rounded-lg p-3">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Badge color="red">Video Gen</Badge>
|
||||
<span className="font-bold text-sm">Wan 2.1 / LTX-Video via ComfyUI</span>
|
||||
</div>
|
||||
<p className="text-xs text-gray-600">Short videos for social media, product demos</p>
|
||||
<div className="mt-2 text-xs space-y-1">
|
||||
<p>• Wan 2.1 (14B) — best quality, uses full 48GB</p>
|
||||
<p>• Wan 2.1 (1.3B) — fast, only ~8GB VRAM</p>
|
||||
<p>• LTX-Video — fastest, ~12GB VRAM, 768x512</p>
|
||||
<p>• ⚠️ Unload LLM before running video gen (shared VRAM)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="VRAM Management Strategy">
|
||||
<div className="bg-gray-50 p-4 rounded-lg">
|
||||
<p className="text-sm font-semibold mb-3">48GB total — you can't run everything simultaneously</p>
|
||||
<div className="space-y-3">
|
||||
<div className="bg-white p-3 rounded border-l-4 border-green-500">
|
||||
<p className="font-semibold text-xs">Mode 1: Content Writing (Default)</p>
|
||||
<p className="text-xs text-gray-500 mt-1">Qwen3 32B (~20GB) + FLUX.1 image gen (~12GB) = ~32GB</p>
|
||||
<p className="text-xs text-green-600 mt-1">✓ Fits comfortably, both can run simultaneously</p>
|
||||
</div>
|
||||
<div className="bg-white p-3 rounded border-l-4 border-blue-500">
|
||||
<p className="font-semibold text-xs">Mode 2: Fast Throughput</p>
|
||||
<p className="text-xs text-gray-500 mt-1">Qwen3 30B-A3B MoE (~19GB) + FLUX.1 (~12GB) = ~31GB</p>
|
||||
<p className="text-xs text-blue-600 mt-1">✓ Blazing fast text + images together</p>
|
||||
</div>
|
||||
<div className="bg-white p-3 rounded border-l-4 border-red-500">
|
||||
<p className="font-semibold text-xs">Mode 3: Video Generation</p>
|
||||
<p className="text-xs text-gray-500 mt-1">Unload LLM → Wan 2.1 14B uses full 48GB</p>
|
||||
<p className="text-xs text-red-600 mt-1">⚠️ Schedule video jobs during off-peak, unload text model first</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-xs text-gray-500 mt-3">Ollama auto-unloads models after 5min idle. Use <code className="bg-gray-200 px-1 rounded">OLLAMA_KEEP_ALIVE</code> to control.</p>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="Secure Connection (SSH Tunnel)">
|
||||
<pre className="bg-gray-900 text-green-400 text-xs p-4 rounded-lg overflow-x-auto whitespace-pre-wrap">{`# Run on Hostinger VPS — creates persistent tunnel to Vast.ai
|
||||
# This makes Vast.ai's ports available on localhost
|
||||
|
||||
# Install autossh for persistent tunnels
|
||||
apt install autossh
|
||||
|
||||
# Create tunnel (run as systemd service)
|
||||
autossh -M 0 -N \\
|
||||
-L 11434:localhost:11434 \\ # Ollama
|
||||
-L 8188:localhost:8188 \\ # ComfyUI
|
||||
-o "ServerAliveInterval=30" \\
|
||||
-o "ServerAliveCountMax=3" \\
|
||||
-i /root/.ssh/vastai_key \\
|
||||
root@VAST_AI_IP -p VAST_SSH_PORT
|
||||
|
||||
# Now on Hostinger:
|
||||
# localhost:11434 → Vast.ai Ollama
|
||||
# localhost:8188 → Vast.ai ComfyUI`}</pre>
|
||||
</Section>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tab === "models" && (
|
||||
<div>
|
||||
<Section title="Text Generation — For IGNY8 Content" defaultOpen={true}>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-xs">
|
||||
<thead>
|
||||
<tr className="bg-gray-50">
|
||||
<th className="text-left p-2">Model</th>
|
||||
<th className="text-left p-2">VRAM</th>
|
||||
<th className="text-left p-2">Speed</th>
|
||||
<th className="text-left p-2">Best For</th>
|
||||
<th className="text-left p-2">License</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr className="border-b bg-green-50">
|
||||
<td className="p-2 font-bold">Qwen3 32B ⭐</td>
|
||||
<td className="p-2">~20GB</td>
|
||||
<td className="p-2">~15-25 tok/s</td>
|
||||
<td className="p-2">Long-form SEO content, articles</td>
|
||||
<td className="p-2"><Badge color="green">Apache 2.0</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b bg-blue-50">
|
||||
<td className="p-2 font-bold">Qwen3 30B-A3B ⭐</td>
|
||||
<td className="p-2">~19GB</td>
|
||||
<td className="p-2">~40-60 tok/s</td>
|
||||
<td className="p-2">Fast chat, SEO meta, bulk content</td>
|
||||
<td className="p-2"><Badge color="green">Apache 2.0</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b">
|
||||
<td className="p-2">Qwen3 14B</td>
|
||||
<td className="p-2">~9GB</td>
|
||||
<td className="p-2">~30-50 tok/s</td>
|
||||
<td className="p-2">Concurrent light tasks</td>
|
||||
<td className="p-2"><Badge color="green">Apache 2.0</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b">
|
||||
<td className="p-2">Qwen3 8B</td>
|
||||
<td className="p-2">~5GB</td>
|
||||
<td className="p-2">~50-80 tok/s</td>
|
||||
<td className="p-2">Classification, tagging, simple tasks</td>
|
||||
<td className="p-2"><Badge color="green">Apache 2.0</Badge></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="mt-3 bg-green-50 p-3 rounded-lg text-xs">
|
||||
<strong>IGNY8 Strategy:</strong> Use 30B-A3B MoE as default (fast bulk content), switch to 32B dense for premium long-form articles. Ollama handles model switching automatically.
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="Image Generation — For IGNY8 Visuals">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-xs">
|
||||
<thead>
|
||||
<tr className="bg-gray-50">
|
||||
<th className="text-left p-2">Model</th>
|
||||
<th className="text-left p-2">VRAM</th>
|
||||
<th className="text-left p-2">Speed</th>
|
||||
<th className="text-left p-2">Quality</th>
|
||||
<th className="text-left p-2">License</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr className="border-b bg-teal-50">
|
||||
<td className="p-2 font-bold">FLUX.1 [dev] ⭐</td>
|
||||
<td className="p-2">~12GB</td>
|
||||
<td className="p-2">~8-15s/img</td>
|
||||
<td className="p-2">Excellent — rivals Midjourney</td>
|
||||
<td className="p-2"><Badge color="orange">Non-commercial*</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b bg-green-50">
|
||||
<td className="p-2 font-bold">Stable Diffusion 3.5 ⭐</td>
|
||||
<td className="p-2">~8GB</td>
|
||||
<td className="p-2">~5-10s/img</td>
|
||||
<td className="p-2">Very good + huge ecosystem</td>
|
||||
<td className="p-2"><Badge color="green">Community</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b">
|
||||
<td className="p-2">SDXL-Lightning</td>
|
||||
<td className="p-2">~6GB</td>
|
||||
<td className="p-2">~1-2s/img</td>
|
||||
<td className="p-2">Good for fast iterations</td>
|
||||
<td className="p-2"><Badge color="green">Open</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b">
|
||||
<td className="p-2">Z-Image-Turbo</td>
|
||||
<td className="p-2">~16GB</td>
|
||||
<td className="p-2"><1s/img</td>
|
||||
<td className="p-2">Excellent + text rendering</td>
|
||||
<td className="p-2"><Badge color="green">Apache 2.0</Badge></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="mt-3 bg-orange-50 p-3 rounded-lg text-xs">
|
||||
<strong>*FLUX.1 [dev] licensing:</strong> Free for non-commercial. For IGNY8 commercial use, either get BFL license or use SD 3.5 / Z-Image-Turbo (Apache 2.0, fully commercial).
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="Video Generation — For IGNY8 Social Content">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-xs">
|
||||
<thead>
|
||||
<tr className="bg-gray-50">
|
||||
<th className="text-left p-2">Model</th>
|
||||
<th className="text-left p-2">VRAM</th>
|
||||
<th className="text-left p-2">Resolution</th>
|
||||
<th className="text-left p-2">Duration</th>
|
||||
<th className="text-left p-2">License</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr className="border-b bg-red-50">
|
||||
<td className="p-2 font-bold">Wan 2.1 (1.3B) ⭐</td>
|
||||
<td className="p-2">~8GB</td>
|
||||
<td className="p-2">480p</td>
|
||||
<td className="p-2">5-8s clips</td>
|
||||
<td className="p-2"><Badge color="green">Apache 2.0</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b bg-blue-50">
|
||||
<td className="p-2 font-bold">LTX-Video ⭐</td>
|
||||
<td className="p-2">~12GB</td>
|
||||
<td className="p-2">768x512</td>
|
||||
<td className="p-2">5-7s clips</td>
|
||||
<td className="p-2"><Badge color="green">Apache 2.0</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b">
|
||||
<td className="p-2">Wan 2.1 (14B)</td>
|
||||
<td className="p-2">~40GB+</td>
|
||||
<td className="p-2">720p</td>
|
||||
<td className="p-2">5-10s clips</td>
|
||||
<td className="p-2"><Badge color="green">Apache 2.0</Badge></td>
|
||||
</tr>
|
||||
<tr className="border-b">
|
||||
<td className="p-2">Wan2GP (optimized)</td>
|
||||
<td className="p-2">~12GB</td>
|
||||
<td className="p-2">720p</td>
|
||||
<td className="p-2">8-15s clips</td>
|
||||
<td className="p-2"><Badge color="green">Open</Badge></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="mt-3 bg-blue-50 p-3 rounded-lg text-xs">
|
||||
<strong>Best approach:</strong> Use Wan 2.1 1.3B or LTX-Video for quick social clips alongside the LLM. For premium 720p video, schedule Wan 14B during off-peak (requires unloading LLM).
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="Running Models Simultaneously">
|
||||
<div className="bg-gray-50 p-4 rounded-lg text-xs space-y-2">
|
||||
<p className="font-bold text-sm mb-2">48GB VRAM Budget — Practical Combos:</p>
|
||||
<div className="bg-white p-2 rounded border border-green-300">
|
||||
<strong>🟢 Combo A (Daily IGNY8 ops):</strong> Qwen3 30B-A3B (19GB) + SD 3.5 images (8GB) + Wan 1.3B video (8GB) = 35GB ✓
|
||||
</div>
|
||||
<div className="bg-white p-2 rounded border border-blue-300">
|
||||
<strong>🔵 Combo B (Premium content):</strong> Qwen3 32B (20GB) + FLUX.1 images (12GB) = 32GB ✓
|
||||
</div>
|
||||
<div className="bg-white p-2 rounded border border-orange-300">
|
||||
<strong>🟠 Combo C (Video focus):</strong> Wan 14B video (40GB+) = needs all VRAM, unload everything else
|
||||
</div>
|
||||
<div className="bg-white p-2 rounded border border-purple-300">
|
||||
<strong>🟣 Combo D (Multi-client chat):</strong> Qwen3 14B (9GB) × multiple concurrent users = fast, lightweight
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tab === "setup" && (
|
||||
<div>
|
||||
<Section title="Phase 1: Hostinger VPS Setup" defaultOpen={true}>
|
||||
<Step num={1} title="Get VPS & Install Docker" code={`# SSH into your Hostinger VPS
|
||||
ssh root@your-vps-ip
|
||||
|
||||
# Install Docker
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
docker compose version # verify
|
||||
|
||||
# Install Plesk (if not pre-installed)
|
||||
sh <(curl https://autoinstall.plesk.com/one-click-installer)`} />
|
||||
<Step num={2} title="Deploy the AI Stack" code={`# Create project directory
|
||||
mkdir -p /opt/ai-stack && cd /opt/ai-stack
|
||||
|
||||
# Create docker-compose.yml (as shown in Hostinger tab)
|
||||
# Create litellm_config.yaml
|
||||
|
||||
# Launch everything
|
||||
docker compose up -d
|
||||
|
||||
# Verify all services
|
||||
docker compose ps`} />
|
||||
<Step num={3} title="Setup Nginx + SSL" code={`# Install certbot
|
||||
apt install certbot python3-certbot-nginx
|
||||
|
||||
# Get SSL certs for your subdomains
|
||||
certbot --nginx -d flowise.yourdomain.com
|
||||
certbot --nginx -d chat.yourdomain.com
|
||||
certbot --nginx -d api.yourdomain.com
|
||||
|
||||
# Setup nginx configs (as shown in Hostinger tab)`} />
|
||||
</Section>
|
||||
|
||||
<Section title="Phase 2: Vast.ai GPU Server Setup">
|
||||
<Step num={1} title="Rent & SSH into GPU" code={`# Rent m:49870 (or your chosen instance)
|
||||
# Vast.ai gives you SSH command like:
|
||||
ssh -p PORT root@VAST_IP -L 8080:localhost:8080
|
||||
|
||||
# First check GPU
|
||||
nvidia-smi # Should show 2x RTX 3090`} />
|
||||
<Step num={2} title="Install Ollama + Models" code={`# Install Ollama
|
||||
curl -fsSL https://ollama.com/install.sh | sh
|
||||
|
||||
# Start Ollama (listen on all interfaces for tunnel)
|
||||
OLLAMA_HOST=0.0.0.0 ollama serve &
|
||||
|
||||
# Pull Qwen3 models
|
||||
ollama pull qwen3:32b # ~20GB, best quality
|
||||
ollama pull qwen3:30b-a3b # ~19GB, fastest
|
||||
ollama pull qwen3:14b # ~9GB, lightweight
|
||||
ollama pull qwen3:8b # ~5GB, ultra-light
|
||||
|
||||
# Test
|
||||
ollama run qwen3:30b-a3b "Write a 100-word SEO article about coffee"`} />
|
||||
<Step num={3} title="Install ComfyUI (Image + Video)" code={`# Install ComfyUI
|
||||
cd /root
|
||||
git clone https://github.com/comfyanonymous/ComfyUI.git
|
||||
cd ComfyUI
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Download image models
|
||||
cd models/checkpoints/
|
||||
# Stable Diffusion 3.5
|
||||
wget https://huggingface.co/stabilityai/stable-diffusion-3.5-large/resolve/main/sd3.5_large.safetensors
|
||||
|
||||
# Download FLUX.1 (if desired)
|
||||
# wget from HuggingFace...
|
||||
|
||||
# Download video models
|
||||
cd /root/ComfyUI/models/
|
||||
# Install Wan2GP for optimized video gen
|
||||
cd /root
|
||||
git clone https://github.com/deepbeepmeep/Wan2GP.git
|
||||
cd Wan2GP && pip install -r requirements.txt
|
||||
|
||||
# Start ComfyUI
|
||||
cd /root/ComfyUI
|
||||
python main.py --listen 0.0.0.0 --port 8188 &`} />
|
||||
<Step num={4} title="Create Persistent SSH Tunnel from Hostinger" code={`# On Hostinger VPS — install autossh
|
||||
apt install autossh
|
||||
|
||||
# Generate SSH key (if not done)
|
||||
ssh-keygen -t ed25519 -f /root/.ssh/vastai_key
|
||||
|
||||
# Copy key to Vast.ai
|
||||
ssh-copy-id -i /root/.ssh/vastai_key -p PORT root@VAST_IP
|
||||
|
||||
# Create systemd service for persistent tunnel
|
||||
cat > /etc/systemd/system/vastai-tunnel.service << 'EOF'
|
||||
[Unit]
|
||||
Description=SSH Tunnel to Vast.ai GPU
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/autossh -M 0 -N \\
|
||||
-L 11434:localhost:11434 \\
|
||||
-L 8188:localhost:8188 \\
|
||||
-o "ServerAliveInterval=30" \\
|
||||
-o "ServerAliveCountMax=3" \\
|
||||
-o "StrictHostKeyChecking=no" \\
|
||||
-i /root/.ssh/vastai_key \\
|
||||
root@VAST_IP -p PORT
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl enable vastai-tunnel
|
||||
systemctl start vastai-tunnel`} />
|
||||
</Section>
|
||||
|
||||
<Section title="Phase 3: Connect Everything">
|
||||
<Step num={1} title="Update LiteLLM config to use tunnel" code={`# litellm_config.yaml — now uses localhost (via tunnel)
|
||||
model_list:
|
||||
- model_name: qwen3-32b
|
||||
litellm_params:
|
||||
model: ollama/qwen3:32b
|
||||
api_base: http://localhost:11434
|
||||
|
||||
- model_name: qwen3-30b-moe
|
||||
litellm_params:
|
||||
model: ollama/qwen3:30b-a3b
|
||||
api_base: http://localhost:11434
|
||||
|
||||
# Restart LiteLLM
|
||||
docker compose restart litellm`} />
|
||||
<Step num={2} title="Configure Flowise for IGNY8" code={`# In Flowise UI (flowise.yourdomain.com):
|
||||
# 1. Add ChatOllama node → set base URL: http://litellm:4000
|
||||
# 2. Set model: qwen3-30b-moe (for content writing)
|
||||
# 3. Add Chroma vector store → URL: http://chromadb:8000
|
||||
# 4. Build your IGNY8 content pipeline:
|
||||
# Prompt → Qwen3 → SEO optimizer → Output
|
||||
|
||||
# For image generation in IGNY8:
|
||||
# Use HTTP Request node → http://localhost:8188/api/prompt
|
||||
# Send ComfyUI workflow JSON for image generation`} />
|
||||
<Step num={3} title="Test the Full Pipeline" code={`# Test LLM via LiteLLM
|
||||
curl http://localhost:4000/v1/chat/completions \\
|
||||
-H "Content-Type: application/json" \\
|
||||
-H "Authorization: Bearer sk-your-key" \\
|
||||
-d '{
|
||||
"model": "qwen3-30b-moe",
|
||||
"messages": [{"role": "user", "content": "Write SEO meta for a coffee shop"}]
|
||||
}'
|
||||
|
||||
# Test ComfyUI image gen
|
||||
curl http://localhost:8188/api/prompt \\
|
||||
-H "Content-Type: application/json" \\
|
||||
-d '{"prompt": {...comfyui_workflow_json...}}'
|
||||
|
||||
# Test Open WebUI
|
||||
# Visit chat.yourdomain.com → should connect to Ollama models`} />
|
||||
</Section>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tab === "costs" && (
|
||||
<div>
|
||||
<Section title="Monthly Cost Breakdown" defaultOpen={true}>
|
||||
<div className="space-y-1 mb-4">
|
||||
<CostRow item="Hostinger VPS (KVM 4)" monthly="~$16-25/mo" notes="16GB RAM, 4 vCPU — Plesk + AI stack" />
|
||||
<CostRow item="Vast.ai GPU (m:49870)" monthly="~$200/mo" notes="2x RTX 3090, 48GB VRAM — 24/7" />
|
||||
<CostRow item="Domains / SSL" monthly="~$5/mo" notes="Subdomains for services" />
|
||||
<CostRow item="Plesk License" monthly="~$15/mo" notes="Web Admin Edition (or use free alternatives)" />
|
||||
</div>
|
||||
<div className="bg-gray-900 text-white p-4 rounded-xl">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="font-bold text-lg">Total Monthly</span>
|
||||
<span className="font-black text-2xl text-green-400">~$235-245/mo</span>
|
||||
</div>
|
||||
<p className="text-xs text-gray-400 mt-1">For unlimited AI text + image + video generation</p>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="vs. API Costs Comparison">
|
||||
<div className="space-y-3">
|
||||
<div className="bg-red-50 border border-red-200 p-3 rounded-lg">
|
||||
<p className="font-bold text-sm text-red-800">If Using APIs Instead:</p>
|
||||
<div className="text-xs text-red-700 mt-2 space-y-1">
|
||||
<p>• OpenAI GPT-4o: ~$0.005/1K tokens → 1M tokens/day = $150/mo just for text</p>
|
||||
<p>• Midjourney: $30/mo (limited) or $0.01-0.04/image</p>
|
||||
<p>• Runway Gen-3: $0.05/sec video → 100 videos/mo = $250/mo</p>
|
||||
<p>• DALL-E 3: $0.04/image → 500 images/mo = $20/mo</p>
|
||||
<p className="font-bold mt-2">Conservative estimate: $400-600+/month with scale</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-green-50 border border-green-200 p-3 rounded-lg">
|
||||
<p className="font-bold text-sm text-green-800">Your Self-Hosted Setup:</p>
|
||||
<div className="text-xs text-green-700 mt-2 space-y-1">
|
||||
<p>• Unlimited text generation — $0 marginal cost</p>
|
||||
<p>• Unlimited image generation — $0 marginal cost</p>
|
||||
<p>• Unlimited video generation — $0 marginal cost</p>
|
||||
<p>• Fixed cost regardless of usage volume</p>
|
||||
<p className="font-bold mt-2">Fixed: ~$240/month — scales to infinity</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section title="When This Pays for Itself">
|
||||
<div className="bg-gray-50 p-4 rounded-lg text-xs space-y-2">
|
||||
<p><strong>Break-even point:</strong> Once IGNY8 processes ~50+ articles/month with images, self-hosting is cheaper than APIs.</p>
|
||||
<p><strong>At scale:</strong> If IGNY8 generates 500+ articles + 1000+ images + 100+ videos per month, you're saving $300-500+/month vs APIs.</p>
|
||||
<p><strong>Added bonus:</strong> No rate limits, no API key management, no vendor lock-in, full data privacy.</p>
|
||||
<p><strong>Revenue potential:</strong> Sell the same infrastructure as a service to Alorig clients — chat.yourdomain.com as a white-label AI assistant.</p>
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-8 bg-gray-50 rounded-xl p-4 text-xs text-gray-500">
|
||||
<p className="font-bold text-gray-700 mb-2">Architecture Summary</p>
|
||||
<p>Hostinger VPS handles web hosting (Plesk), AI orchestration (Flowise, LiteLLM, Open WebUI), and vector storage (Chroma). All AI inference routes through an SSH tunnel to Vast.ai's 2x RTX 3090 GPU server running Ollama (text), ComfyUI (images + video). Zero API costs — fixed monthly spend of ~$240 for unlimited generation.</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
602
v2/Igny8 V2 New Final Plans/IGNY8-Industry-Sector-Master-List.md
Normal file
602
v2/Igny8 V2 New Final Plans/IGNY8-Industry-Sector-Master-List.md
Normal file
@@ -0,0 +1,602 @@
|
||||
# IGNY8 Industry & Sector Master List v2
|
||||
|
||||
**Validation test for every sector:** "Could someone build and sustain a dedicated SEO-driven website for this sector alone? Does it have its own distinct attribute framework?"
|
||||
|
||||
**Validation test for industry grouping:** "Do all sectors within this industry share a common business domain, but each requires a fundamentally different set of attributes?"
|
||||
|
||||
---
|
||||
|
||||
## 1. Healthcare & Medical
|
||||
1. General Practice & Family Medicine
|
||||
2. Dentistry & Oral Health
|
||||
3. Mental Health & Counseling
|
||||
4. Physiotherapy & Rehabilitation
|
||||
5. Dermatology & Skin Clinics
|
||||
6. Eye Care & Optometry
|
||||
7. Chiropractic Care
|
||||
8. Cosmetic & Plastic Surgery
|
||||
9. Pediatrics & Child Health
|
||||
10. Orthopedics & Sports Medicine
|
||||
11. Cardiology & Heart Health
|
||||
12. Oncology & Cancer Care
|
||||
13. Home Healthcare Services
|
||||
14. Urgent Care & Walk-In Clinics
|
||||
|
||||
## 2. Wellness & Alternative Medicine
|
||||
1. Massage Therapy & Bodywork
|
||||
2. Acupuncture & Traditional Chinese Medicine
|
||||
3. Ayurveda & Herbal Medicine
|
||||
4. Homeopathic Medicine
|
||||
5. Naturopathy & Holistic Health
|
||||
6. Nutrition & Dietetics
|
||||
7. Yoga & Meditation Services
|
||||
8. Wellness Retreats & Spas
|
||||
9. Functional & Integrative Medicine
|
||||
10. Energy Healing & Reiki
|
||||
|
||||
## 3. Health & Fitness
|
||||
1. Gyms & Fitness Centers
|
||||
2. Personal Training Services
|
||||
3. Yoga Studios
|
||||
4. Pilates Studios
|
||||
5. Martial Arts Schools
|
||||
6. CrossFit & Functional Training
|
||||
7. Dance Studios
|
||||
8. Swimming & Aquatic Fitness
|
||||
9. Sports Coaching & Academies
|
||||
10. Kids & Youth Fitness Programs
|
||||
|
||||
## 4. Health Products & Supplements
|
||||
1. Dietary Supplements & Vitamins
|
||||
2. Fitness Equipment & Gear
|
||||
3. Massage & Therapy Devices
|
||||
4. Relaxation & Sleep Products
|
||||
5. Weight Loss Products
|
||||
6. Senior Health & Mobility Aids
|
||||
7. Medical Equipment & Supplies
|
||||
8. First Aid & Safety Products
|
||||
9. Disability & Accessibility Products
|
||||
10. Health Monitoring Devices
|
||||
|
||||
## 5. Beauty & Personal Care
|
||||
1. Skincare Products & Brands
|
||||
2. Haircare Products & Brands
|
||||
3. Makeup & Cosmetics
|
||||
4. Fragrances & Perfumes
|
||||
5. Men's Grooming Products
|
||||
6. Nail Care Products
|
||||
7. Organic & Natural Beauty
|
||||
8. Beauty Tools & Devices
|
||||
9. Anti-Aging Products & Treatments
|
||||
10. Sun Care & Tanning Products
|
||||
|
||||
## 6. Beauty & Personal Care Services
|
||||
1. Hair Salons & Styling
|
||||
2. Barber Shops
|
||||
3. Nail Salons
|
||||
4. Spa & Wellness Centers
|
||||
5. Skin Treatment & Facial Clinics
|
||||
6. Laser Hair Removal Services
|
||||
7. Tattoo & Body Art Studios
|
||||
8. Eyebrow & Lash Services
|
||||
9. Bridal & Occasion Styling
|
||||
10. Mobile Beauty Services
|
||||
|
||||
## 7. Apparel & Fashion
|
||||
1. Womenswear
|
||||
2. Menswear
|
||||
3. Kidswear & Baby Clothing
|
||||
4. Footwear
|
||||
5. Fashion Accessories (Bags, Scarves, Belts)
|
||||
6. Sportswear & Activewear
|
||||
7. Luxury & Designer Fashion
|
||||
8. Ethnic & Cultural Wear
|
||||
9. Uniforms & Workwear
|
||||
10. Plus Size & Inclusive Fashion
|
||||
11. Sustainable & Eco Fashion
|
||||
12. Lingerie & Sleepwear
|
||||
|
||||
## 8. Jewelry & Watches
|
||||
1. Fine Jewelry (Gold, Diamond, Gemstone)
|
||||
2. Fashion & Costume Jewelry
|
||||
3. Wedding & Bridal Jewelry
|
||||
4. Luxury Watches
|
||||
5. Casual & Fashion Watches
|
||||
6. Handmade & Artisan Jewelry
|
||||
7. Men's Jewelry & Accessories
|
||||
8. Religious & Cultural Jewelry
|
||||
9. Jewelry Repair & Custom Design
|
||||
10. Smart Watches & Wearables
|
||||
|
||||
## 9. Pets & Animals
|
||||
1. Dog Products & Supplies
|
||||
2. Cat Products & Supplies
|
||||
3. Bird & Aviary Supplies
|
||||
4. Aquarium & Fish Supplies
|
||||
5. Small Animal Supplies (Rabbit, Hamster)
|
||||
6. Reptile & Exotic Pet Supplies
|
||||
7. Pet Food & Nutrition
|
||||
8. Pet Grooming Products & Services
|
||||
9. Veterinary Services
|
||||
10. Pet Training & Behavior
|
||||
|
||||
## 10. Home & Furniture
|
||||
1. Living Room Furniture
|
||||
2. Bedroom Furniture & Mattresses
|
||||
3. Kitchen & Dining Furniture
|
||||
4. Office & Home Office Furniture
|
||||
5. Outdoor & Patio Furniture
|
||||
6. Children's Furniture & Nursery
|
||||
7. Bathroom Furniture & Fixtures
|
||||
8. Storage & Organization Solutions
|
||||
9. Custom & Bespoke Furniture
|
||||
10. Antique & Vintage Furniture
|
||||
|
||||
## 11. Home Decor & Interior
|
||||
1. Home Decor & Accessories
|
||||
2. Wall Art & Frames
|
||||
3. Lighting & Lamps
|
||||
4. Curtains, Blinds & Window Treatments
|
||||
5. Rugs & Carpets
|
||||
6. Bedding, Pillows & Linen
|
||||
7. Candles, Fragrances & Aromatherapy
|
||||
8. Vases, Planters & Indoor Greenery
|
||||
9. Mirrors & Decorative Glass
|
||||
10. Interior Design Services
|
||||
|
||||
## 12. Home Appliances & Kitchen
|
||||
1. Large Kitchen Appliances
|
||||
2. Small Kitchen Appliances & Gadgets
|
||||
3. Cookware & Bakeware
|
||||
4. Kitchen Utensils & Tools
|
||||
5. Food Storage & Organization
|
||||
6. Coffee & Beverage Machines
|
||||
7. Laundry Appliances
|
||||
8. Vacuum Cleaners & Floor Care
|
||||
9. Air Purifiers & Climate Control
|
||||
10. Home Water Filtration
|
||||
|
||||
## 13. Garden & Outdoor Living
|
||||
1. Garden Tools & Equipment
|
||||
2. Plants, Seeds & Gardening
|
||||
3. Outdoor Furniture & Decor
|
||||
4. Lawn Care & Landscaping Products
|
||||
5. BBQ & Outdoor Cooking
|
||||
6. Greenhouses & Grow Equipment
|
||||
7. Fencing & Garden Structures
|
||||
8. Irrigation & Water Features
|
||||
9. Pest & Weed Control
|
||||
10. Swimming Pool Supplies & Equipment
|
||||
|
||||
## 14. Electronics & Gadgets
|
||||
1. Mobile Phones & Accessories
|
||||
2. Laptops & Computers
|
||||
3. Audio & Headphones
|
||||
4. Cameras & Photography
|
||||
5. Smart Home Devices
|
||||
6. Wearable Technology
|
||||
7. Gaming Consoles & Accessories
|
||||
8. Drones & Robotics
|
||||
9. Networking & Wi-Fi Equipment
|
||||
10. Computer Components & PC Building
|
||||
11. Printers & Office Equipment
|
||||
12. TV & Home Entertainment
|
||||
|
||||
## 15. Baby & Kids
|
||||
1. Baby Gear (Strollers, Car Seats, Carriers)
|
||||
2. Baby Clothing & Accessories
|
||||
3. Toys & Games
|
||||
4. Nursery Furniture & Decor
|
||||
5. Baby Feeding & Nursing
|
||||
6. Baby Health & Safety
|
||||
7. Kids Educational Products
|
||||
8. Kids Outdoor & Play Equipment
|
||||
9. Maternity & Pregnancy Products
|
||||
10. Diapering & Potty Training
|
||||
|
||||
## 16. Sports & Outdoors
|
||||
1. Cycling & Bikes
|
||||
2. Running & Athletics Gear
|
||||
3. Swimming & Water Sports
|
||||
4. Camping & Hiking Gear
|
||||
5. Team Sports Equipment (Soccer, Cricket, Basketball)
|
||||
6. Golf Equipment & Accessories
|
||||
7. Fishing Gear & Tackle
|
||||
8. Hunting & Shooting Sports
|
||||
9. Winter Sports (Skiing, Snowboarding)
|
||||
10. Racquet Sports (Tennis, Badminton, Squash)
|
||||
11. Combat & Martial Arts Equipment
|
||||
12. Boating & Marine Equipment
|
||||
|
||||
## 17. Automotive
|
||||
1. Auto Repair & Maintenance Services
|
||||
2. Auto Parts & Accessories
|
||||
3. Car Detailing & Care Products
|
||||
4. Tires & Wheels
|
||||
5. Car Dealerships (New & Used)
|
||||
6. Car Rental & Leasing
|
||||
7. Auto Body & Collision Repair
|
||||
8. Electric Vehicles & EV Accessories
|
||||
9. Motorcycles & Powersports
|
||||
10. Commercial Vehicles & Fleet
|
||||
11. Car Audio & Electronics
|
||||
12. Automotive Tools & Equipment
|
||||
|
||||
## 18. Food & Beverage (Products)
|
||||
1. Specialty & Gourmet Food
|
||||
2. Organic & Health Food
|
||||
3. Snacks & Confectionery
|
||||
4. Coffee & Tea Products
|
||||
5. Halal Food Products
|
||||
6. Vegan & Plant-Based Food
|
||||
7. Baby & Kids Food
|
||||
8. Spices, Sauces & Condiments
|
||||
9. Bakery & Baking Supplies
|
||||
10. Beverages & Drinks
|
||||
|
||||
## 19. Food & Beverage (Services)
|
||||
1. Restaurants & Dining
|
||||
2. Cafes & Coffee Shops
|
||||
3. Fast Food & Quick Service
|
||||
4. Bakeries & Pastry Shops
|
||||
5. Catering Services
|
||||
6. Food Delivery & Meal Kits
|
||||
7. Food Trucks & Street Food
|
||||
8. Bars & Nightlife
|
||||
9. Butcher & Meat Shops
|
||||
10. Cloud Kitchens & Virtual Restaurants
|
||||
|
||||
## 20. Home Services
|
||||
1. Plumbing Services
|
||||
2. Electrical Services
|
||||
3. HVAC (Heating & Cooling)
|
||||
4. Roofing Services
|
||||
5. Landscaping & Lawn Care
|
||||
6. Residential Cleaning Services
|
||||
7. Pest Control Services
|
||||
8. Painting & Decorating Services
|
||||
9. Flooring Installation & Services
|
||||
10. Window & Door Installation
|
||||
11. Garage Door Services
|
||||
12. Locksmith Services
|
||||
13. Moving & Relocation Services
|
||||
14. Handyman & General Repairs
|
||||
15. Swimming Pool Services
|
||||
|
||||
## 21. Construction & Building
|
||||
1. General Contracting
|
||||
2. Residential Construction
|
||||
3. Commercial Construction
|
||||
4. Interior Design & Fit-Out
|
||||
5. Architecture & Design
|
||||
6. Concrete & Masonry
|
||||
7. Structural Steel & Fabrication
|
||||
8. Carpentry & Woodworking
|
||||
9. Demolition & Site Preparation
|
||||
10. Plumbing & Mechanical Contractors (Commercial)
|
||||
|
||||
## 22. Real Estate & Property
|
||||
1. Residential Real Estate
|
||||
2. Commercial Real Estate
|
||||
3. Property Management
|
||||
4. Property Development
|
||||
5. Real Estate Investment
|
||||
6. Vacation & Short-Term Rentals
|
||||
7. Co-Working & Office Space
|
||||
8. Warehouse & Industrial Property
|
||||
9. Land Sales & Development
|
||||
10. Real Estate Agents & Brokers
|
||||
|
||||
## 23. Legal Services
|
||||
1. Personal Injury Law
|
||||
2. Family & Divorce Law
|
||||
3. Criminal Defense
|
||||
4. Corporate & Business Law
|
||||
5. Immigration Law
|
||||
6. Employment & Labor Law
|
||||
7. Estate Planning & Probate
|
||||
8. Intellectual Property Law
|
||||
9. Real Estate & Property Law
|
||||
10. Tax Law & Disputes
|
||||
|
||||
## 24. Financial Services & Insurance
|
||||
1. Banking & Personal Finance
|
||||
2. Insurance (Auto, Health, Home, Life)
|
||||
3. Accounting & Bookkeeping
|
||||
4. Tax Preparation & Planning
|
||||
5. Investment & Wealth Management
|
||||
6. Mortgage & Home Loans
|
||||
7. Business Loans & SME Finance
|
||||
8. Financial Planning & Advisory
|
||||
9. Islamic Finance & Banking
|
||||
10. Cryptocurrency & Digital Assets
|
||||
11. Debt Management & Credit Repair
|
||||
12. Payroll & HR Finance
|
||||
|
||||
## 25. Education & Training
|
||||
1. Online Learning & E-Learning Platforms
|
||||
2. Tutoring & Academic Support
|
||||
3. Test Preparation (SAT, GRE, IELTS, etc.)
|
||||
4. Vocational & Skills Training
|
||||
5. Language Schools & Courses
|
||||
6. Driving Schools
|
||||
7. Music & Arts Education
|
||||
8. Early Childhood & Preschool Education
|
||||
9. Higher Education & Universities
|
||||
10. Corporate Training & Development
|
||||
11. IT & Coding Training
|
||||
12. Special Needs Education
|
||||
|
||||
## 26. Hospitality & Tourism
|
||||
1. Hotels & Resorts
|
||||
2. Travel Agencies & Tour Operators
|
||||
3. Vacation Rentals & Homestays
|
||||
4. Adventure & Eco Tourism
|
||||
5. Medical Tourism
|
||||
6. Business & Corporate Travel
|
||||
7. Cruise & Ocean Travel
|
||||
8. Destination Weddings & Honeymoons
|
||||
9. Airlines & Air Travel
|
||||
10. Hajj & Umrah Travel Services
|
||||
|
||||
## 27. Technology & Software
|
||||
1. Project Management Software
|
||||
2. CRM & Sales Tools
|
||||
3. HR & Recruitment Software
|
||||
4. Accounting & Finance Software
|
||||
5. Marketing Automation & Email Tools
|
||||
6. Cybersecurity Solutions
|
||||
7. Data Analytics & BI Tools
|
||||
8. E-Commerce Platforms & Tools
|
||||
9. Customer Support & Help Desk
|
||||
10. Collaboration & Communication Tools
|
||||
11. Cloud & Infrastructure Services
|
||||
12. Website Builders & CMS
|
||||
13. AI & Machine Learning Platforms
|
||||
14. ERP & Business Management Systems
|
||||
|
||||
## 28. IT & Tech Services
|
||||
1. IT Consulting & Managed Services
|
||||
2. Web Design & Development
|
||||
3. Mobile App Development
|
||||
4. Software Development & Custom Solutions
|
||||
5. Cloud Migration & Management
|
||||
6. Network & Infrastructure Services
|
||||
7. Data Recovery & Backup Services
|
||||
8. IT Support & Help Desk Services
|
||||
9. Digital Transformation Consulting
|
||||
10. Internet Service Providers & Hosting
|
||||
|
||||
## 29. Marketing & Advertising
|
||||
1. Digital Marketing Agencies
|
||||
2. SEO Services
|
||||
3. Social Media Marketing
|
||||
4. Content Marketing & Strategy
|
||||
5. PPC & Paid Advertising
|
||||
6. Email Marketing Services
|
||||
7. Branding & Brand Strategy
|
||||
8. Influencer Marketing
|
||||
9. PR & Communications
|
||||
10. Video Marketing & Production
|
||||
|
||||
## 30. Media & Creative Services
|
||||
1. Photography Services
|
||||
2. Videography & Film Production
|
||||
3. Graphic Design & Branding
|
||||
4. Animation & Motion Graphics
|
||||
5. Music Production & Audio
|
||||
6. Podcast Production
|
||||
7. Content Writing & Copywriting
|
||||
8. Printing & Publishing
|
||||
9. Sign Making & Signage
|
||||
10. Promotional Products & Merchandise
|
||||
|
||||
## 31. Staffing & Recruitment
|
||||
1. General Recruitment Agencies
|
||||
2. IT & Tech Recruitment
|
||||
3. Healthcare Recruitment
|
||||
4. Executive Search & Headhunting
|
||||
5. Temporary & Contract Staffing
|
||||
6. Blue Collar & Industrial Staffing
|
||||
7. International Recruitment & Manpower
|
||||
8. Recruitment Technology & Job Boards
|
||||
|
||||
## 32. Professional & Business Services
|
||||
1. Management Consulting
|
||||
2. Business Process Outsourcing (BPO)
|
||||
3. Virtual Assistants & Remote Support
|
||||
4. Translation & Localization
|
||||
5. Market Research & Analytics
|
||||
6. Engineering & Technical Consulting
|
||||
7. Environmental & Sustainability Consulting
|
||||
8. Import/Export & Trade Consulting
|
||||
9. Franchise Consulting
|
||||
10. Business Coaching & Mentoring
|
||||
|
||||
## 33. Agriculture & Farming
|
||||
1. Agricultural Equipment & Machinery
|
||||
2. Seeds, Fertilizers & Agrochemicals
|
||||
3. Livestock & Poultry Farming
|
||||
4. Dairy & Dairy Products
|
||||
5. Irrigation & Water Management
|
||||
6. Organic Farming & Products
|
||||
7. Aquaculture & Fisheries
|
||||
8. Horticulture & Nurseries
|
||||
9. Agri-Tech & Precision Farming
|
||||
10. Agricultural Consulting
|
||||
|
||||
## 34. Logistics & Transport
|
||||
1. Freight & Cargo Shipping
|
||||
2. Courier & Parcel Delivery
|
||||
3. Warehousing & Storage
|
||||
4. Fleet Management & Tracking
|
||||
5. Moving & Relocation Services (Commercial)
|
||||
6. Cold Chain Logistics
|
||||
7. Customs Brokerage & Import/Export
|
||||
8. Last Mile Delivery
|
||||
9. Trucking & Road Transport
|
||||
10. Maritime & Ocean Shipping
|
||||
|
||||
## 35. Energy & Utilities
|
||||
1. Solar Energy & Installation
|
||||
2. Generators & Power Solutions
|
||||
3. Wind Energy
|
||||
4. Battery & Energy Storage
|
||||
5. Electrical Contracting
|
||||
6. Energy Auditing & Management
|
||||
7. Water Treatment & Purification
|
||||
8. EV Charging Infrastructure
|
||||
9. Oil & Gas Services
|
||||
|
||||
## 36. Events & Weddings
|
||||
1. Wedding Planning & Coordination
|
||||
2. Event Planning & Management
|
||||
3. Venue Hire & Banquet Halls
|
||||
4. Event & Wedding Photography
|
||||
5. Event & Wedding Catering
|
||||
6. DJ, Music & Entertainment
|
||||
7. Event Decoration & Floristry
|
||||
8. Wedding Attire & Bridal
|
||||
9. Corporate Events & Conferences
|
||||
10. Party & Event Rentals
|
||||
|
||||
## 37. Security & Safety
|
||||
1. Home Security & Alarm Systems
|
||||
2. Commercial Security Services
|
||||
3. CCTV & Video Surveillance
|
||||
4. Fire Safety & Protection
|
||||
5. Access Control Systems
|
||||
6. Cybersecurity Services
|
||||
7. Security Guard & Patrol
|
||||
8. Private Investigation
|
||||
9. Workplace Safety & Compliance
|
||||
|
||||
## 38. Cleaning & Waste Management
|
||||
1. Residential Cleaning
|
||||
2. Commercial & Office Cleaning
|
||||
3. Carpet & Upholstery Cleaning
|
||||
4. Window Cleaning
|
||||
5. Pressure Washing & Exterior Cleaning
|
||||
6. Industrial Cleaning
|
||||
7. Janitorial Supplies & Equipment
|
||||
8. Disinfection & Sanitization
|
||||
9. Waste Management & Recycling
|
||||
10. Junk Removal & Hauling
|
||||
|
||||
## 39. Manufacturing & Industrial
|
||||
1. Metal & Steel Manufacturing
|
||||
2. Plastic & Polymer Products
|
||||
3. Textile & Fabric Manufacturing
|
||||
4. Chemical Products & Coatings
|
||||
5. Packaging & Containers
|
||||
6. Industrial Machinery & Equipment
|
||||
7. Electronics Manufacturing
|
||||
8. Food Processing
|
||||
9. Pharmaceutical Manufacturing
|
||||
10. Automotive Parts Manufacturing
|
||||
|
||||
## 40. Religious & Cultural
|
||||
1. Islamic Products & Supplies
|
||||
2. Hajj & Umrah Services
|
||||
3. Modest Fashion & Islamic Clothing
|
||||
4. Religious Books & Educational Materials
|
||||
5. Halal Products & Certification
|
||||
6. Cultural Handicrafts & Artifacts
|
||||
7. Pilgrimage & Spiritual Travel
|
||||
8. Religious Education & Courses
|
||||
|
||||
## 41. Nonprofit & Social Enterprise
|
||||
1. Charitable Organizations
|
||||
2. Community Development
|
||||
3. Social Enterprise & Impact
|
||||
4. Fundraising & Donor Platforms
|
||||
5. Environmental & Conservation NGOs
|
||||
6. Humanitarian & Relief Organizations
|
||||
7. Youth & Education Nonprofits
|
||||
|
||||
## 42. Telecom & Connectivity
|
||||
1. Internet Service Providers
|
||||
2. Mobile & Wireless Services
|
||||
3. VoIP & Business Communication
|
||||
4. Managed IT & Network Services
|
||||
5. Domain & Web Hosting
|
||||
6. Cable & Satellite Services
|
||||
7. Telecom Equipment & Infrastructure
|
||||
|
||||
## 43. Office & Stationery
|
||||
1. Office Furniture
|
||||
2. Office Supplies & Stationery
|
||||
3. Writing Instruments & Art Supplies
|
||||
4. Bags, Backpacks & Luggage
|
||||
5. Planners, Diaries & Organizers
|
||||
6. Gift Items & Novelties
|
||||
7. Paper & Printing Supplies
|
||||
|
||||
## 44. Books & Media
|
||||
1. Books & Publishing
|
||||
2. E-Books & Digital Content
|
||||
3. Magazines & Periodicals
|
||||
4. Music & Vinyl
|
||||
5. Board Games & Puzzles
|
||||
6. Educational Materials & Textbooks
|
||||
7. Audiobooks & Podcasts
|
||||
|
||||
## 45. Tobacco & Vaping
|
||||
1. Vaping & E-Cigarettes
|
||||
2. Cigars & Tobacco Products
|
||||
3. Smoking Accessories
|
||||
4. CBD & Hemp Products
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| # | Industry | Sectors | Notes |
|
||||
|---|----------|---------|-------|
|
||||
| 1 | Healthcare & Medical | 14 | Specialized medical practices |
|
||||
| 2 | Wellness & Alternative Medicine | 10 | Non-conventional health services |
|
||||
| 3 | Health & Fitness | 10 | Exercise & fitness service businesses |
|
||||
| 4 | Health Products & Supplements | 10 | Health-related e-commerce |
|
||||
| 5 | Beauty & Personal Care | 10 | Beauty product e-commerce |
|
||||
| 6 | Beauty & Personal Care Services | 10 | Beauty service businesses |
|
||||
| 7 | Apparel & Fashion | 12 | Clothing e-commerce |
|
||||
| 8 | Jewelry & Watches | 10 | Jewelry/watch e-commerce & services |
|
||||
| 9 | Pets & Animals | 10 | Pet products & services |
|
||||
| 10 | Home & Furniture | 10 | Furniture e-commerce |
|
||||
| 11 | Home Decor & Interior | 10 | Decor products & services |
|
||||
| 12 | Home Appliances & Kitchen | 10 | Appliance e-commerce |
|
||||
| 13 | Garden & Outdoor Living | 10 | Outdoor products |
|
||||
| 14 | Electronics & Gadgets | 12 | Consumer electronics e-commerce |
|
||||
| 15 | Baby & Kids | 10 | Baby/kids products |
|
||||
| 16 | Sports & Outdoors | 12 | Sports equipment & gear |
|
||||
| 17 | Automotive | 12 | Auto products & services |
|
||||
| 18 | Food & Beverage (Products) | 10 | Food product e-commerce |
|
||||
| 19 | Food & Beverage (Services) | 10 | Restaurant & food service businesses |
|
||||
| 20 | Home Services | 15 | Trade & maintenance services |
|
||||
| 21 | Construction & Building | 10 | Construction trades |
|
||||
| 22 | Real Estate & Property | 10 | Property business |
|
||||
| 23 | Legal Services | 10 | Law practices |
|
||||
| 24 | Financial Services & Insurance | 12 | Finance & insurance |
|
||||
| 25 | Education & Training | 12 | Education businesses |
|
||||
| 26 | Hospitality & Tourism | 10 | Travel & hospitality |
|
||||
| 27 | Technology & Software | 14 | SaaS products |
|
||||
| 28 | IT & Tech Services | 10 | IT service businesses |
|
||||
| 29 | Marketing & Advertising | 10 | Marketing agencies & services |
|
||||
| 30 | Media & Creative Services | 10 | Creative service businesses |
|
||||
| 31 | Staffing & Recruitment | 8 | Recruitment businesses |
|
||||
| 32 | Professional & Business Services | 10 | Consulting & advisory |
|
||||
| 33 | Agriculture & Farming | 10 | Agri products & services |
|
||||
| 34 | Logistics & Transport | 10 | Shipping & logistics |
|
||||
| 35 | Energy & Utilities | 9 | Energy products & services |
|
||||
| 36 | Events & Weddings | 10 | Event service businesses |
|
||||
| 37 | Security & Safety | 9 | Security products & services |
|
||||
| 38 | Cleaning & Waste Management | 10 | Cleaning service businesses |
|
||||
| 39 | Manufacturing & Industrial | 10 | Manufacturing businesses |
|
||||
| 40 | Religious & Cultural | 8 | Religious products & services |
|
||||
| 41 | Nonprofit & Social Enterprise | 7 | Nonprofit organizations |
|
||||
| 42 | Telecom & Connectivity | 7 | Telecom businesses |
|
||||
| 43 | Office & Stationery | 7 | Office product e-commerce |
|
||||
| 44 | Books & Media | 7 | Books & media e-commerce |
|
||||
| 45 | Tobacco & Vaping | 4 | Restricted product e-commerce |
|
||||
|
||||
**Total: 45 Industries, 449 Sectors**
|
||||
798
v2/Igny8 V2 New Final Plans/IGNY8-Plugin-Build-Plan.md
Normal file
798
v2/Igny8 V2 New Final Plans/IGNY8-Plugin-Build-Plan.md
Normal file
@@ -0,0 +1,798 @@
|
||||
# IGNY8 WordPress Plugin — Complete Build Plan
|
||||
|
||||
**By:** Alorig Systems
|
||||
**For:** AI Agent (Claude Code / Opus 4.6 in VSCode)
|
||||
**Version:** 1.0
|
||||
**Date:** March 2026
|
||||
**Status:** Reference Document for Development
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The IGNY8 WordPress Plugin is the **first site-level SEO plugin for WordPress**. Unlike Yoast, RankMath, or AIOSEO — which optimize individual pages against individual keywords — IGNY8 analyzes and optimizes your entire site's architecture, taxonomy structure, internal linking graph, and topical authority.
|
||||
|
||||
**Two modes:**
|
||||
1. **Standalone (Free):** Full SEO plugin replacing Yoast/RankMath — meta tags, schema, sitemaps, redirects, social OG, analytics, GSC, internal linking analysis, site-level architecture insights. No IGNY8 app account needed.
|
||||
2. **Connected (Premium):** Links to IGNY8 SaaS platform — AI content generation, SAG blueprint sync, automated taxonomy creation, content pipeline, automated publishing, full site architecture generation.
|
||||
|
||||
**Distribution:** Free on WordPress.org repository. Connected features require IGNY8 app subscription.
|
||||
|
||||
---
|
||||
|
||||
## Part 1: Product Positioning
|
||||
|
||||
### 1.1 What Exists Today (Page-Level Plugins)
|
||||
|
||||
Every current SEO plugin does essentially the same thing:
|
||||
- Set a focus keyword per page
|
||||
- Analyze keyword density, heading usage, meta length
|
||||
- Generate XML sitemap
|
||||
- Add meta tags and OG tags
|
||||
- Basic schema markup
|
||||
- Redirect manager
|
||||
|
||||
They optimize pages in isolation. They have no concept of how pages relate to each other, whether your site has topical gaps, whether your taxonomy structure creates authority, or whether your internal linking flows power to the right pages.
|
||||
|
||||
### 1.2 What IGNY8 Plugin Does Differently
|
||||
|
||||
**Site-Level Intelligence (Free):**
|
||||
- Taxonomy coverage analysis: "You have 45 categories but only 12 have content — 33 are empty archive pages hurting your authority"
|
||||
- Orphan page detection: "These 28 posts have zero internal links pointing to them"
|
||||
- Topical gap analysis: "Your site covers 'dog food' extensively but has zero content about 'dog nutrition' — a closely related topic your competitors rank for"
|
||||
- Internal link graph visualization: which pages are over-linked, under-linked, or isolated
|
||||
- Cluster detection: automatically groups existing content into topical clusters and identifies imbalances
|
||||
- Thin content identification: pages below content thresholds that need expansion
|
||||
- Cannibalization detection: multiple pages targeting the same keyword
|
||||
|
||||
**Site Architecture Generation (Connected):**
|
||||
- SAG blueprint sync: receive the full dimensional structure (attributes, clusters, keywords) from IGNY8 platform
|
||||
- Automated taxonomy creation: create all WordPress taxonomies, terms, and hierarchies from the SAG blueprint
|
||||
- Content pipeline: pull AI-generated content for posts, pages, term descriptions, hub pages
|
||||
- Publishing automation: scheduled publishing with review workflow
|
||||
- Ongoing optimization: content updates, new cluster detection, gap filling
|
||||
|
||||
### 1.3 The Free → Connected Funnel
|
||||
|
||||
User installs free plugin → sees site-level insights they've never had before → dashboard shows: "IGNY8 has identified 23 topical gaps and 15 missing taxonomy terms. Connect to IGNY8 to generate the full blueprint and auto-fill these gaps." → User signs up for IGNY8 app → Connects via API key → Full architecture generation begins.
|
||||
|
||||
The free plugin must be genuinely excellent. Not a crippled demo. A real replacement for RankMath that makes people switch.
|
||||
|
||||
---
|
||||
|
||||
## Part 2: Module Architecture
|
||||
|
||||
### 2.1 Module Map
|
||||
|
||||
| Module | Free | Connected | Replaces |
|
||||
|---|---|---|---|
|
||||
| **SEO Core** | ✅ Full | ✅ Enhanced | Yoast, RankMath, AIOSEO |
|
||||
| **Schema** | ✅ Full | ✅ Enhanced | Schema Pro, JSON-LD plugins |
|
||||
| **Sitemap** | ✅ Full | ✅ Full | Yoast sitemap, XML Sitemap Generator |
|
||||
| **Redirects** | ✅ Full | ✅ Full | Redirection plugin |
|
||||
| **Social & OG** | ✅ Full | ✅ Enhanced | Social Warfare, OG plugins |
|
||||
| **Analytics** | ✅ Full | ✅ Full | MonsterInsights, GA plugins |
|
||||
| **Site Intelligence** | ✅ Basic | ✅ Full | Nothing (unique) |
|
||||
| **Internal Linking** | ✅ Suggestions | ✅ Auto-linking | Link Whisper |
|
||||
| **GSC Integration** | ✅ Dashboard | ✅ Full + Indexing API | Search Console plugins |
|
||||
| **Content Sync** | ❌ | ✅ Full | — |
|
||||
| **SAG Structure** | ❌ | ✅ Full | — |
|
||||
| **Taxonomy Manager** | ❌ | ✅ Full | — |
|
||||
| **Socializer** | ✅ Basic sharing | ✅ Auto-posting | Buffer, Hootsuite |
|
||||
| **SMTP** | ✅ Full | ✅ Full | WP Mail SMTP |
|
||||
|
||||
### 2.2 Free vs Connected Feature Split
|
||||
|
||||
**SEO Core — Free:**
|
||||
- Focus keyword per post/page
|
||||
- SEO title + meta description with SERP preview
|
||||
- Canonical URL management
|
||||
- Robots meta (index/noindex, follow/nofollow)
|
||||
- Content analysis (keyword density, headings, readability, internal links)
|
||||
- Title tag template system (site-wide patterns)
|
||||
- Breadcrumb generation + schema
|
||||
- Webmaster verification codes
|
||||
|
||||
**SEO Core — Connected additions:**
|
||||
- Multi-keyword optimization (primary + secondary keywords from cluster)
|
||||
- Cluster-aware content scoring ("this post covers 60% of its cluster's keyword targets")
|
||||
- Auto-suggest missing headings based on cluster keyword gaps
|
||||
- Content freshness scoring and update recommendations
|
||||
|
||||
**Site Intelligence — Free (Basic):**
|
||||
- Total page count by type (posts, pages, products, terms)
|
||||
- Orphan pages list (no internal links)
|
||||
- Thin content list (below word count threshold)
|
||||
- Empty taxonomy terms list
|
||||
- Basic internal link count per page
|
||||
- Duplicate title/meta detection
|
||||
- Cannibalization warnings (same keyword on multiple pages)
|
||||
|
||||
**Site Intelligence — Connected (Full):**
|
||||
- Full SAG gap analysis (missing clusters, missing terms, missing attribute values)
|
||||
- Cluster health scores (content coverage, link density, keyword rankings per cluster)
|
||||
- Competitor gap comparison (connected to IGNY8 platform competitor analysis)
|
||||
- Architecture blueprint with recommended new pages/terms
|
||||
- Priority queue: which gaps to fill first (by volume, difficulty, existing authority)
|
||||
- Topical authority scoring per cluster
|
||||
|
||||
**Internal Linking — Free:**
|
||||
- Link audit: total internal links, broken links, nofollow links
|
||||
- Per-post link count and suggestions ("this post could link to these 5 related posts")
|
||||
- Orphan content detection
|
||||
- Link equity distribution overview
|
||||
|
||||
**Internal Linking — Connected:**
|
||||
- SAG-aware automatic link suggestions based on cluster relationships
|
||||
- Bulk link insertion tool
|
||||
- Link template rules ("always link [keyword] to [URL]")
|
||||
- Contextual link placement (AI-determined best anchor text and position)
|
||||
- Link priority scoring based on cluster importance
|
||||
|
||||
**Socializer — Free:**
|
||||
- Lightweight share buttons (pure CSS/JS, no external dependencies)
|
||||
- Position options: floating, above/below content, inline
|
||||
- Networks: Facebook, X, LinkedIn, Pinterest, WhatsApp, Telegram, Email, Copy Link
|
||||
- Social profile links management (site-wide)
|
||||
- OG tags (handled by SEO Core module)
|
||||
|
||||
**Socializer — Connected:**
|
||||
- Auto-post to social platforms on WordPress publish
|
||||
- Per-platform message templates
|
||||
- Scheduling (publish now or delay)
|
||||
- Platform API connections: X, Facebook Pages, LinkedIn, Instagram
|
||||
- Dynamic OG image generation from post title + featured image
|
||||
- Social post performance tracking (clicks, engagement)
|
||||
- Bulk social scheduling for existing content
|
||||
|
||||
---
|
||||
|
||||
## Part 3: Plugin File Structure
|
||||
|
||||
```
|
||||
igny8/
|
||||
├── igny8.php # Plugin header, bootstrap, module loader
|
||||
├── readme.txt # WordPress.org readme
|
||||
├── uninstall.php # Cleanup on uninstall
|
||||
│
|
||||
├── includes/
|
||||
│ ├── class-igny8.php # Main plugin class
|
||||
│ ├── class-module-manager.php # Module registration + activation
|
||||
│ ├── class-api-client.php # IGNY8 platform API client (for connected mode)
|
||||
│ ├── class-connection.php # API key validation, connection status
|
||||
│ ├── class-utils.php # Shared utilities
|
||||
│ ├── class-ajax.php # Shared AJAX handler
|
||||
│ ├── class-rest-api.php # Plugin REST endpoints for theme communication
|
||||
│ ├── class-compatibility.php # Detect and disable conflicting plugins
|
||||
│ │
|
||||
│ ├── modules/
|
||||
│ │ │
|
||||
│ │ ├── seo/
|
||||
│ │ │ ├── class-seo-module.php # Module entry, hooks
|
||||
│ │ │ ├── class-meta-box.php # Post/page SEO meta box
|
||||
│ │ │ ├── class-title-tag.php # Title tag management + templates
|
||||
│ │ │ ├── class-meta-tags.php # Meta description, robots, canonical
|
||||
│ │ │ ├── class-content-analysis.php # Real-time SEO scoring
|
||||
│ │ │ ├── class-breadcrumbs.php # Breadcrumb generation + shortcode
|
||||
│ │ │ ├── class-opengraph.php # OG + Twitter Card meta tags
|
||||
│ │ │ ├── class-robots-txt.php # Virtual robots.txt manager
|
||||
│ │ │ ├── class-verification.php # Webmaster tool verification codes
|
||||
│ │ │ └── views/
|
||||
│ │ │ ├── meta-box.php # Meta box template
|
||||
│ │ │ └── settings.php # SEO settings page template
|
||||
│ │ │
|
||||
│ │ ├── schema/
|
||||
│ │ │ ├── class-schema-module.php # Module entry
|
||||
│ │ │ ├── class-schema-generator.php # JSON-LD output
|
||||
│ │ │ ├── class-schema-article.php # Article, BlogPosting, NewsArticle
|
||||
│ │ │ ├── class-schema-local-business.php # LocalBusiness + subtypes
|
||||
│ │ │ ├── class-schema-product.php # Product (WooCommerce integration)
|
||||
│ │ │ ├── class-schema-faq.php # FAQPage
|
||||
│ │ │ ├── class-schema-howto.php # HowTo
|
||||
│ │ │ ├── class-schema-organization.php # Organization / Person
|
||||
│ │ │ ├── class-schema-webpage.php # WebPage, CollectionPage
|
||||
│ │ │ ├── class-schema-breadcrumb.php # BreadcrumbList
|
||||
│ │ │ ├── class-schema-service.php # Service (for service CPT)
|
||||
│ │ │ └── class-schema-custom.php # Custom schema field (advanced users)
|
||||
│ │ │
|
||||
│ │ ├── sitemap/
|
||||
│ │ │ ├── class-sitemap-module.php # Module entry
|
||||
│ │ │ ├── class-sitemap-index.php # Sitemap index generator
|
||||
│ │ │ ├── class-sitemap-posts.php # Post type sitemaps
|
||||
│ │ │ ├── class-sitemap-taxonomies.php # Taxonomy sitemaps
|
||||
│ │ │ ├── class-sitemap-images.php # Image sitemap
|
||||
│ │ │ └── class-sitemap-xsl.php # XSL stylesheet for browser viewing
|
||||
│ │ │
|
||||
│ │ ├── redirects/
|
||||
│ │ │ ├── class-redirects-module.php # Module entry
|
||||
│ │ │ ├── class-redirect-manager.php # CRUD for redirects
|
||||
│ │ │ ├── class-404-monitor.php # 404 logging + one-click redirect
|
||||
│ │ │ ├── class-auto-redirect.php # Auto-redirect on slug change
|
||||
│ │ │ └── views/
|
||||
│ │ │ └── redirects-admin.php # Redirect management page
|
||||
│ │ │
|
||||
│ │ ├── analytics/
|
||||
│ │ │ ├── class-analytics-module.php # Module entry
|
||||
│ │ │ ├── class-ga-connector.php # Google Analytics (GA4)
|
||||
│ │ │ ├── class-gtm-connector.php # Google Tag Manager
|
||||
│ │ │ ├── class-pixel-manager.php # Facebook, TikTok, Pinterest pixels
|
||||
│ │ │ └── class-script-manager.php # Custom header/footer scripts
|
||||
│ │ │
|
||||
│ │ ├── site-intelligence/
|
||||
│ │ │ ├── class-intelligence-module.php # Module entry
|
||||
│ │ │ ├── class-site-audit.php # Full site audit runner
|
||||
│ │ │ ├── class-orphan-detector.php # Pages with no internal links
|
||||
│ │ │ ├── class-thin-content.php # Below-threshold content
|
||||
│ │ │ ├── class-empty-terms.php # Taxonomy terms with no content
|
||||
│ │ │ ├── class-cannibalization.php # Keyword cannibalization detection
|
||||
│ │ │ ├── class-duplicate-meta.php # Duplicate titles/descriptions
|
||||
│ │ │ ├── class-cluster-detector.php # Auto-group existing content into clusters
|
||||
│ │ │ ├── class-gap-analysis.php # [Connected] SAG gap analysis
|
||||
│ │ │ ├── class-cluster-health.php # [Connected] Per-cluster scoring
|
||||
│ │ │ └── views/
|
||||
│ │ │ ├── dashboard.php # Site intelligence dashboard
|
||||
│ │ │ └── audit-results.php # Detailed audit results page
|
||||
│ │ │
|
||||
│ │ ├── linking/
|
||||
│ │ │ ├── class-linking-module.php # Module entry
|
||||
│ │ │ ├── class-link-auditor.php # Internal link audit
|
||||
│ │ │ ├── class-link-suggestions.php # Per-post link suggestions
|
||||
│ │ │ ├── class-orphan-links.php # Orphan content list
|
||||
│ │ │ ├── class-link-graph.php # Link equity distribution map
|
||||
│ │ │ ├── class-auto-linker.php # [Connected] Automatic link insertion
|
||||
│ │ │ ├── class-link-rules.php # [Connected] Keyword → URL link rules
|
||||
│ │ │ └── views/
|
||||
│ │ │ ├── link-audit.php # Link audit page
|
||||
│ │ │ └── link-suggestions.php # Suggestions interface
|
||||
│ │ │
|
||||
│ │ ├── gsc/
|
||||
│ │ │ ├── class-gsc-module.php # Module entry
|
||||
│ │ │ ├── class-gsc-auth.php # Google OAuth flow
|
||||
│ │ │ ├── class-gsc-dashboard.php # Search performance dashboard
|
||||
│ │ │ ├── class-gsc-keywords.php # Keyword position tracking
|
||||
│ │ │ ├── class-gsc-indexing.php # [Connected] Indexing API requests
|
||||
│ │ │ ├── class-gsc-url-inspection.php # [Connected] URL inspection status
|
||||
│ │ │ └── views/
|
||||
│ │ │ ├── gsc-dashboard.php # GSC data display
|
||||
│ │ │ └── gsc-connect.php # OAuth connection page
|
||||
│ │ │
|
||||
│ │ ├── socializer/
|
||||
│ │ │ ├── class-socializer-module.php # Module entry
|
||||
│ │ │ ├── class-share-buttons.php # Frontend share buttons (pure CSS/JS)
|
||||
│ │ │ ├── class-social-profiles.php # Site-wide social links
|
||||
│ │ │ ├── class-auto-poster.php # [Connected] Auto-post on publish
|
||||
│ │ │ ├── class-twitter-api.php # [Connected] X/Twitter API
|
||||
│ │ │ ├── class-facebook-api.php # [Connected] Facebook Pages API
|
||||
│ │ │ ├── class-linkedin-api.php # [Connected] LinkedIn API
|
||||
│ │ │ ├── class-og-image-generator.php # [Connected] Dynamic OG images
|
||||
│ │ │ └── views/
|
||||
│ │ │ ├── share-settings.php # Share button configuration
|
||||
│ │ │ └── social-accounts.php # Connected accounts management
|
||||
│ │ │
|
||||
│ │ ├── smtp/
|
||||
│ │ │ ├── class-smtp-module.php # Module entry
|
||||
│ │ │ ├── class-smtp-mailer.php # Override wp_mail()
|
||||
│ │ │ ├── class-email-log.php # Send log
|
||||
│ │ │ └── class-email-test.php # Test email utility
|
||||
│ │ │
|
||||
│ │ ├── content-sync/ # [Connected only]
|
||||
│ │ │ ├── class-sync-module.php # Module entry
|
||||
│ │ │ ├── class-content-puller.php # Pull content from IGNY8 app
|
||||
│ │ │ ├── class-content-mapper.php # Map IGNY8 content types → WP post types
|
||||
│ │ │ ├── class-image-downloader.php # Download + attach AI images
|
||||
│ │ │ ├── class-sync-queue.php # Sync job queue + status
|
||||
│ │ │ ├── class-publish-scheduler.php # Scheduled publishing with review
|
||||
│ │ │ └── views/
|
||||
│ │ │ ├── sync-dashboard.php # Sync status + controls
|
||||
│ │ │ └── content-review.php # Review queue before publish
|
||||
│ │ │
|
||||
│ │ └── sag/ # [Connected only]
|
||||
│ │ ├── class-sag-module.php # Module entry
|
||||
│ │ ├── class-blueprint-sync.php # Receive SAG blueprint from IGNY8 app
|
||||
│ │ ├── class-taxonomy-builder.php # Create WP taxonomies from SAG attributes
|
||||
│ │ ├── class-term-builder.php # Create taxonomy terms from attribute values
|
||||
│ │ ├── class-cluster-manager.php # Cluster → hub page mapping
|
||||
│ │ ├── class-structure-visualizer.php # Visual site structure map
|
||||
│ │ └── views/
|
||||
│ │ ├── sag-dashboard.php # SAG structure overview
|
||||
│ │ ├── blueprint-review.php # Review blueprint before applying
|
||||
│ │ └── structure-map.php # Visual cluster/taxonomy map
|
||||
│ │
|
||||
│ ├── admin/
|
||||
│ │ ├── class-admin-menu.php # Admin menu registration
|
||||
│ │ ├── class-dashboard.php # Main plugin dashboard
|
||||
│ │ ├── class-setup-wizard.php # First-run setup wizard
|
||||
│ │ ├── class-compatibility-notice.php # Notices for conflicting plugins
|
||||
│ │ ├── views/
|
||||
│ │ │ ├── dashboard.php # Main dashboard template
|
||||
│ │ │ ├── wizard/
|
||||
│ │ │ │ ├── step-1-site-type.php # Site type selection
|
||||
│ │ │ │ ├── step-2-seo-import.php # Import from Yoast/RankMath
|
||||
│ │ │ │ ├── step-3-basics.php # Site name, logo, org type
|
||||
│ │ │ │ ├── step-4-social.php # Social profiles
|
||||
│ │ │ │ ├── step-5-connect.php # IGNY8 API key (optional)
|
||||
│ │ │ │ └── step-6-done.php # Summary + next steps
|
||||
│ │ │ └── connect-prompt.php # "Connect to IGNY8" upsell card
|
||||
│ │ └── assets/
|
||||
│ │ ├── admin.css
|
||||
│ │ ├── admin.js
|
||||
│ │ ├── meta-box.css
|
||||
│ │ └── meta-box.js
|
||||
│ │
|
||||
│ ├── frontend/
|
||||
│ │ ├── class-head-output.php # All <head> tag output (meta, schema, OG)
|
||||
│ │ ├── class-share-output.php # Share button HTML/CSS/JS
|
||||
│ │ └── assets/
|
||||
│ │ ├── share-buttons.css # Share button styles (<3KB)
|
||||
│ │ └── share-buttons.js # Share button JS (<2KB)
|
||||
│ │
|
||||
│ ├── data/
|
||||
│ │ ├── class-installer.php # Database table creation
|
||||
│ │ ├── class-migrator.php # Version migration handler
|
||||
│ │ └── class-importer.php # Import from Yoast/RankMath/AIOSEO
|
||||
│ │
|
||||
│ └── integrations/
|
||||
│ ├── class-woocommerce.php # WooCommerce-specific SEO/schema
|
||||
│ └── class-theme-bridge.php # Communication layer with companion theme
|
||||
│
|
||||
└── languages/
|
||||
└── igny8.pot
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Part 4: Data Architecture
|
||||
|
||||
### 4.1 Custom Database Tables
|
||||
|
||||
```sql
|
||||
-- Redirects
|
||||
{prefix}igny8_redirects
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY
|
||||
source_url VARCHAR(500) NOT NULL
|
||||
target_url VARCHAR(500) NOT NULL
|
||||
type SMALLINT DEFAULT 301 -- 301, 302, 307
|
||||
hits INT DEFAULT 0
|
||||
last_hit DATETIME NULL
|
||||
created_at DATETIME NOT NULL
|
||||
is_active TINYINT(1) DEFAULT 1
|
||||
INDEX idx_source (source_url(191))
|
||||
|
||||
-- 404 Log
|
||||
{prefix}igny8_404_log
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY
|
||||
url VARCHAR(500) NOT NULL
|
||||
referrer VARCHAR(500) NULL
|
||||
user_agent VARCHAR(500) NULL
|
||||
ip_hash VARCHAR(64) NULL -- Hashed for privacy
|
||||
hits INT DEFAULT 1
|
||||
first_hit DATETIME NOT NULL
|
||||
last_hit DATETIME NOT NULL
|
||||
is_resolved TINYINT(1) DEFAULT 0
|
||||
redirect_id BIGINT NULL -- FK to redirects table
|
||||
INDEX idx_url (url(191))
|
||||
|
||||
-- Internal Links Map
|
||||
{prefix}igny8_link_map
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY
|
||||
source_post_id BIGINT NOT NULL
|
||||
target_post_id BIGINT NOT NULL
|
||||
anchor_text VARCHAR(500) NULL
|
||||
is_follow TINYINT(1) DEFAULT 1
|
||||
link_position VARCHAR(20) NULL -- content, sidebar, footer
|
||||
last_crawled DATETIME NOT NULL
|
||||
INDEX idx_source (source_post_id)
|
||||
INDEX idx_target (target_post_id)
|
||||
|
||||
-- Site Audit Results
|
||||
{prefix}igny8_audit_results
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY
|
||||
audit_type VARCHAR(50) NOT NULL -- orphan, thin, cannibalization, etc.
|
||||
post_id BIGINT NULL
|
||||
term_id BIGINT NULL
|
||||
severity VARCHAR(20) NOT NULL -- critical, warning, info
|
||||
message TEXT NOT NULL
|
||||
data LONGTEXT NULL -- JSON extra data
|
||||
audit_date DATETIME NOT NULL
|
||||
is_resolved TINYINT(1) DEFAULT 0
|
||||
INDEX idx_type_date (audit_type, audit_date)
|
||||
|
||||
-- Email Log (SMTP module)
|
||||
{prefix}igny8_email_log
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY
|
||||
to_email VARCHAR(320) NOT NULL
|
||||
subject VARCHAR(500) NOT NULL
|
||||
status VARCHAR(20) NOT NULL -- sent, failed
|
||||
error_message TEXT NULL
|
||||
sent_at DATETIME NOT NULL
|
||||
|
||||
-- Form Entries (if forms included — see note below)
|
||||
-- Forms may move to theme plugin instead
|
||||
|
||||
-- Sync Queue (Connected mode)
|
||||
{prefix}igny8_sync_queue
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY
|
||||
igny8_content_id VARCHAR(100) NOT NULL
|
||||
content_type VARCHAR(50) NOT NULL
|
||||
sync_status VARCHAR(20) NOT NULL -- pending, synced, failed, review
|
||||
wp_post_id BIGINT NULL
|
||||
wp_term_id BIGINT NULL
|
||||
data LONGTEXT NULL -- JSON payload from IGNY8
|
||||
created_at DATETIME NOT NULL
|
||||
synced_at DATETIME NULL
|
||||
error_message TEXT NULL
|
||||
INDEX idx_status (sync_status)
|
||||
```
|
||||
|
||||
### 4.2 Post Meta Keys
|
||||
|
||||
All IGNY8 post meta keys use the `_igny8_` prefix:
|
||||
|
||||
```
|
||||
_igny8_focus_keyword -- Primary focus keyword
|
||||
_igny8_secondary_keywords -- JSON array of secondary keywords
|
||||
_igny8_seo_title -- Custom SEO title (overrides template)
|
||||
_igny8_meta_description -- Meta description
|
||||
_igny8_canonical_url -- Canonical URL override
|
||||
_igny8_robots_index -- 1 = index, 0 = noindex
|
||||
_igny8_robots_follow -- 1 = follow, 0 = nofollow
|
||||
_igny8_og_title -- OG title override
|
||||
_igny8_og_description -- OG description override
|
||||
_igny8_og_image -- OG image override (attachment ID)
|
||||
_igny8_twitter_title -- Twitter card title override
|
||||
_igny8_twitter_description -- Twitter card description override
|
||||
_igny8_schema_type -- Schema type override (Article, HowTo, FAQ, etc.)
|
||||
_igny8_schema_custom -- Custom JSON-LD (advanced)
|
||||
_igny8_seo_score -- Last calculated SEO score (0-100)
|
||||
_igny8_content_score -- Content quality score
|
||||
_igny8_readability_score -- Readability score
|
||||
_igny8_cluster_id -- [Connected] Mapped cluster ID
|
||||
_igny8_related_links -- JSON array: [{post_id, anchor_text, priority}]
|
||||
_igny8_link_suggestions -- JSON array of suggested internal links
|
||||
_igny8_last_analysis -- Timestamp of last content analysis
|
||||
_igny8_igny8_content_id -- [Connected] ID in IGNY8 platform
|
||||
_igny8_sync_status -- [Connected] synced, pending, modified
|
||||
```
|
||||
|
||||
### 4.3 Term Meta Keys
|
||||
|
||||
```
|
||||
_igny8_term_seo_title -- SEO title for term archive
|
||||
_igny8_term_meta_description -- Meta description for term archive
|
||||
_igny8_term_robots_index -- index/noindex
|
||||
_igny8_term_og_image -- OG image for term
|
||||
_igny8_term_content -- Rich HTML content for term landing page
|
||||
_igny8_term_cluster_id -- [Connected] Mapped cluster ID
|
||||
_igny8_term_sag_attribute -- [Connected] SAG attribute this term belongs to
|
||||
_igny8_term_sag_level -- [Connected] Primary, Secondary, Tertiary
|
||||
_igny8_term_faq -- JSON array of FAQ items for term
|
||||
_igny8_term_related_terms -- JSON array of related term IDs
|
||||
_igny8_term_igny8_id -- [Connected] ID in IGNY8 platform
|
||||
```
|
||||
|
||||
### 4.4 Options Keys
|
||||
|
||||
```
|
||||
igny8_version -- Plugin version (for migrations)
|
||||
igny8_active_modules -- JSON array of enabled module slugs
|
||||
igny8_seo_settings -- JSON: title templates, separator, defaults
|
||||
igny8_schema_settings -- JSON: org type, name, logo, knowledge graph
|
||||
igny8_sitemap_settings -- JSON: included post types, taxonomies
|
||||
igny8_social_profiles -- JSON: {facebook, twitter, linkedin, youtube, ...}
|
||||
igny8_analytics_settings -- JSON: GA ID, GTM ID, pixel IDs
|
||||
igny8_redirect_settings -- JSON: auto-redirect on slug change, etc.
|
||||
igny8_smtp_settings -- JSON: host, port, user, pass, encryption
|
||||
igny8_share_settings -- JSON: networks, position, style
|
||||
igny8_linking_settings -- JSON: auto-link rules, max links per post
|
||||
igny8_intelligence_settings -- JSON: audit schedule, thresholds
|
||||
igny8_gsc_token -- Encrypted Google OAuth token
|
||||
igny8_gsc_property -- Selected Search Console property
|
||||
igny8_api_key -- [Connected] IGNY8 platform API key
|
||||
igny8_api_connected -- [Connected] boolean
|
||||
igny8_site_id -- [Connected] IGNY8 site ID
|
||||
igny8_last_sync -- [Connected] last sync timestamp
|
||||
igny8_sag_blueprint -- [Connected] JSON: full SAG structure cache
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Part 5: Theme ↔ Plugin Contract
|
||||
|
||||
The IGNY8 plugin communicates with the companion theme (and any theme) through a defined interface. The theme is never required — the plugin works with any theme. But the companion theme knows how to read IGNY8 data natively.
|
||||
|
||||
### 5.1 How Theme Reads Plugin Data
|
||||
|
||||
The plugin registers a public API class that the theme (or any theme) can use:
|
||||
|
||||
```php
|
||||
// Theme checks if IGNY8 is active:
|
||||
if (function_exists('igny8')) {
|
||||
$seo_title = igny8()->seo->get_title($post_id);
|
||||
$breadcrumbs = igny8()->seo->get_breadcrumbs();
|
||||
$related_links = igny8()->linking->get_related_links($post_id);
|
||||
$schema = igny8()->schema->get_json_ld($post_id);
|
||||
$share_buttons = igny8()->socializer->render_share_buttons($post_id);
|
||||
$term_content = igny8()->seo->get_term_content($term_id);
|
||||
$cluster_nav = igny8()->linking->get_cluster_navigation($post_id);
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 What Theme Reads for Display
|
||||
|
||||
| Data | Source | Theme Usage |
|
||||
|---|---|---|
|
||||
| Related links | `_igny8_related_links` post meta | "Related Articles" section |
|
||||
| Cluster navigation | Plugin API: cluster siblings | "More in this topic" sidebar/footer |
|
||||
| Term landing page content | `_igny8_term_content` term meta | Term archive template hero section |
|
||||
| Term FAQs | `_igny8_term_faq` term meta | FAQ accordion on term pages |
|
||||
| Related terms | `_igny8_term_related_terms` term meta | "Related topics" block on term pages |
|
||||
| Breadcrumbs | Plugin API or shortcode `[igny8_breadcrumbs]` | Breadcrumb display |
|
||||
| Share buttons | Plugin API or shortcode `[igny8_share]` | Share button display |
|
||||
| SAG attribute label | `_igny8_term_sag_attribute` term meta | Attribute-based navigation sections |
|
||||
| SEO scores | `_igny8_seo_score` post meta | Optional score badge in admin |
|
||||
|
||||
### 5.3 REST API Endpoints (Plugin Provides)
|
||||
|
||||
For advanced theme features or AJAX interactions:
|
||||
|
||||
```
|
||||
GET /wp-json/igny8/v1/related/{post_id} -- Related content for a post
|
||||
GET /wp-json/igny8/v1/cluster/{cluster_id} -- All content in a cluster
|
||||
GET /wp-json/igny8/v1/term/{term_id}/content -- Term landing page data
|
||||
GET /wp-json/igny8/v1/structure/overview -- Site structure summary
|
||||
POST /wp-json/igny8/v1/sync/trigger -- [Connected] Trigger sync
|
||||
GET /wp-json/igny8/v1/audit/summary -- Site audit summary
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Part 6: SEO Import System
|
||||
|
||||
Critical for adoption. Users switching from Yoast or RankMath need a seamless migration.
|
||||
|
||||
### 6.1 Supported Imports
|
||||
|
||||
| Source Plugin | Data Imported |
|
||||
|---|---|
|
||||
| **Yoast SEO** | Focus keyword, SEO title, meta description, robots meta, canonical, OG settings, redirects (premium), XML sitemap settings |
|
||||
| **RankMath** | Focus keywords (multiple), SEO title, meta description, robots, canonical, OG, schema type, redirects, 404 monitor data |
|
||||
| **AIOSEO** | Title, description, robots, canonical, OG, schema |
|
||||
|
||||
### 6.2 Import Process
|
||||
|
||||
1. Plugin detects installed SEO plugins on activation
|
||||
2. Setup wizard offers import in Step 2
|
||||
3. Import runs in background (Celery-style via WP Cron for large sites)
|
||||
4. Progress bar shows completion
|
||||
5. After import, option to deactivate source plugin
|
||||
6. All imported data stored in IGNY8's own meta keys (no dependency on source plugin data)
|
||||
|
||||
---
|
||||
|
||||
## Part 7: Setup Wizard
|
||||
|
||||
### Step 1: Site Type
|
||||
Select site type for default schema and configuration:
|
||||
- Blog / Content Site
|
||||
- Business / Corporate
|
||||
- eCommerce (WooCommerce)
|
||||
- Local Business / Services
|
||||
- SaaS / Software
|
||||
- Portfolio / Agency
|
||||
|
||||
### Step 2: SEO Import
|
||||
- Detects Yoast, RankMath, AIOSEO
|
||||
- One-click import of all SEO data
|
||||
- Shows count of posts/pages/terms to import
|
||||
|
||||
### Step 3: Site Basics
|
||||
- Site name (for title tag template)
|
||||
- Organization or Person (for schema)
|
||||
- Logo upload (for schema)
|
||||
- Default title separator
|
||||
|
||||
### Step 4: Social Profiles
|
||||
- Facebook, X/Twitter, LinkedIn, YouTube, Instagram, Pinterest URLs
|
||||
- Default social sharing image
|
||||
|
||||
### Step 5: Connect to IGNY8 (Optional)
|
||||
- API key input field
|
||||
- "Don't have an account? Sign up free" link
|
||||
- Connection test + site pairing
|
||||
- Skip option (clearly labeled, no pressure)
|
||||
|
||||
### Step 6: Done
|
||||
- Summary of configuration
|
||||
- "Run your first site audit" CTA
|
||||
- Links to key settings pages
|
||||
- Quick tips for getting started
|
||||
|
||||
---
|
||||
|
||||
## Part 8: Compatibility Layer
|
||||
|
||||
### 8.1 Conflicting Plugin Detection
|
||||
|
||||
On activation, detect and warn about:
|
||||
- Yoast SEO (meta tags, sitemap conflict)
|
||||
- RankMath (meta tags, sitemap, schema conflict)
|
||||
- AIOSEO (meta tags conflict)
|
||||
- XML Sitemap Generator (sitemap conflict)
|
||||
- Schema plugins (duplicate schema)
|
||||
- Redirection plugin (redirect conflict)
|
||||
|
||||
Show admin notice: "IGNY8 replaces [Plugin Name]. We can import your data and you can then deactivate it. [Import & Deactivate] [Dismiss]"
|
||||
|
||||
### 8.2 WooCommerce Integration
|
||||
|
||||
When WooCommerce is active:
|
||||
- Product schema auto-generated from WooCommerce data
|
||||
- Product category term meta available
|
||||
- Product attribute taxonomies detected and included in SAG structure
|
||||
- Shop/product archive pages get SEO meta box
|
||||
- Product sitemap includes price, availability, images
|
||||
|
||||
### 8.3 Theme Bridge
|
||||
|
||||
When companion theme is active:
|
||||
- Plugin detects `current_theme_supports('igny8')`
|
||||
- Enables enhanced data passing (related links, cluster nav, term content)
|
||||
- Disables features the theme handles natively (breadcrumb HTML, share button HTML)
|
||||
- Plugin focuses on data + `<head>` output; theme handles visual display
|
||||
|
||||
When any other theme:
|
||||
- Plugin handles all output itself (breadcrumbs via shortcode, share buttons via auto-insertion)
|
||||
- All features work independently
|
||||
- Less visually integrated but fully functional
|
||||
|
||||
---
|
||||
|
||||
## Part 9: Build Execution Plan
|
||||
|
||||
### Phase 1: Foundation (Days 1-3)
|
||||
|
||||
| Day | Task |
|
||||
|---|---|
|
||||
| 1 | Plugin skeleton: main file, module manager, admin menu, dashboard page |
|
||||
| 1 | Module base class, activation/deactivation lifecycle, option storage |
|
||||
| 2 | Setup wizard: 6-step flow, site type config, social profiles |
|
||||
| 2 | Database installer: create all custom tables |
|
||||
| 3 | REST API base: endpoint registration, authentication |
|
||||
| 3 | Compatibility layer: detect conflicting plugins, admin notices |
|
||||
|
||||
### Phase 2: SEO Core (Days 4-7)
|
||||
|
||||
| Day | Task |
|
||||
|---|---|
|
||||
| 4 | SEO meta box: focus keyword, title, description, SERP preview |
|
||||
| 4 | Title tag management: templates, separator, dynamic tokens |
|
||||
| 5 | Meta tags output: description, robots, canonical in `<head>` |
|
||||
| 5 | Content analysis: keyword density, heading check, readability scoring |
|
||||
| 6 | OG + Twitter Card meta tags |
|
||||
| 6 | Breadcrumbs: generation, shortcode, schema |
|
||||
| 7 | Robots.txt manager, verification codes |
|
||||
| 7 | SEO settings page: global defaults, title templates, noindex rules |
|
||||
|
||||
### Phase 3: Schema + Sitemap + Redirects (Days 8-10)
|
||||
|
||||
| Day | Task |
|
||||
|---|---|
|
||||
| 8 | Schema generator: Article, Organization, WebPage, BreadcrumbList, WebSite+SearchAction |
|
||||
| 8 | Schema: FAQPage, HowTo, LocalBusiness, Service |
|
||||
| 9 | Schema: Product (WooCommerce), custom schema field |
|
||||
| 9 | XML sitemap: index, post type sitemaps, taxonomy sitemaps, image sitemap |
|
||||
| 10 | Redirects: CRUD, 404 monitor, auto-redirect on slug change, CSV import/export |
|
||||
|
||||
### Phase 4: Site Intelligence (Days 11-13)
|
||||
|
||||
| Day | Task |
|
||||
|---|---|
|
||||
| 11 | Site audit runner: orchestrate all checks |
|
||||
| 11 | Orphan detector, thin content scanner, empty terms checker |
|
||||
| 12 | Cannibalization detection, duplicate meta finder |
|
||||
| 12 | Cluster detector (auto-group existing content by topic similarity) |
|
||||
| 13 | Intelligence dashboard: audit results, scores, charts |
|
||||
| 13 | Scheduled re-audit via WP Cron |
|
||||
|
||||
### Phase 5: Internal Linking (Days 14-15)
|
||||
|
||||
| Day | Task |
|
||||
|---|---|
|
||||
| 14 | Link crawl: scan all content, build link map table |
|
||||
| 14 | Link audit page: per-post counts, broken links, orphans |
|
||||
| 15 | Link suggestions: analyze content and suggest internal links |
|
||||
| 15 | Link graph visualization (simple table/chart, not full D3 graph) |
|
||||
|
||||
### Phase 6: Socializer + Analytics + SMTP (Days 16-18)
|
||||
|
||||
| Day | Task |
|
||||
|---|---|
|
||||
| 16 | Share buttons: pure CSS/JS, position options, network selection |
|
||||
| 16 | Social profiles management |
|
||||
| 17 | Analytics: GA4 connector, GTM, pixel manager, custom scripts |
|
||||
| 17 | SMTP: mailer override, email log, test email |
|
||||
| 18 | GSC: OAuth flow, dashboard, keyword tracking display |
|
||||
|
||||
### Phase 7: SEO Import (Days 19-20)
|
||||
|
||||
| Day | Task |
|
||||
|---|---|
|
||||
| 19 | Yoast importer: read all Yoast meta keys, map to IGNY8 keys |
|
||||
| 19 | RankMath importer: read all RankMath meta keys, map to IGNY8 keys |
|
||||
| 20 | AIOSEO importer |
|
||||
| 20 | Import UI: progress bar, background processing, completion report |
|
||||
|
||||
### Phase 8: Connected Mode — Content Sync (Days 21-23)
|
||||
|
||||
| Day | Task |
|
||||
|---|---|
|
||||
| 21 | API client: authenticate with IGNY8 platform, connection management |
|
||||
| 21 | Content puller: fetch content from IGNY8 API |
|
||||
| 22 | Content mapper: map IGNY8 content types to WP post types, handle images |
|
||||
| 22 | Sync queue: pending/synced/failed status, retry logic |
|
||||
| 23 | Publish scheduler: review queue, scheduled publishing |
|
||||
| 23 | Sync dashboard: status, controls, history |
|
||||
|
||||
### Phase 9: Connected Mode — SAG Structure (Days 24-27)
|
||||
|
||||
| Day | Task |
|
||||
|---|---|
|
||||
| 24 | Blueprint sync: receive SAG structure JSON from IGNY8 platform |
|
||||
| 24 | Blueprint review UI: show proposed taxonomies/terms before applying |
|
||||
| 25 | Taxonomy builder: create WordPress taxonomies from SAG attributes |
|
||||
| 25 | Term builder: create terms from attribute values, set hierarchies |
|
||||
| 26 | Cluster manager: map clusters to hub pages/terms |
|
||||
| 26 | Term content sync: populate term descriptions and landing page content |
|
||||
| 27 | Structure visualizer: visual map of clusters → taxonomies → content |
|
||||
| 27 | Connected enhancements: multi-keyword scoring, cluster-aware analysis, auto-linker |
|
||||
|
||||
### Phase 10: Polish + Package (Days 28-30)
|
||||
|
||||
| Day | Task |
|
||||
|---|---|
|
||||
| 28 | Cross-module testing: all modules enabled/disabled combinations |
|
||||
| 28 | Performance: ensure zero frontend impact when features aren't used |
|
||||
| 29 | WordPress.org compliance: readme.txt, screenshots, FAQ |
|
||||
| 29 | Internationalization audit: all strings translatable |
|
||||
| 30 | Build script: generate release zip |
|
||||
| 30 | Documentation: hooks, filters, developer guide |
|
||||
|
||||
---
|
||||
|
||||
## Part 10: Performance Rules
|
||||
|
||||
The plugin must be invisible in terms of frontend performance when features aren't actively outputting content.
|
||||
|
||||
| Rule | Implementation |
|
||||
|---|---|
|
||||
| Zero CSS on frontend unless share buttons are enabled | Conditional enqueue only |
|
||||
| Zero JS on frontend unless share buttons or dynamic features are used | Conditional enqueue |
|
||||
| All `<head>` output in a single hook at priority 1 | No scattered wp_head hooks |
|
||||
| Schema output as single JSON-LD block | Not multiple schema blocks |
|
||||
| Admin assets only on IGNY8 admin pages | Screen check before enqueue |
|
||||
| Meta box assets only on post editor screens | Screen check before enqueue |
|
||||
| Site audit runs via WP Cron, never on page load | Background processing |
|
||||
| Link crawl is background process, never blocks requests | WP Cron scheduled |
|
||||
| All option reads use object cache when available | wp_cache_get/set |
|
||||
| Connected mode API calls are async, never block page load | WP Cron + queue |
|
||||
|
||||
---
|
||||
|
||||
## Part 11: WordPress.org Submission Requirements
|
||||
|
||||
For free distribution on WordPress.org repo:
|
||||
|
||||
- GPL v2+ license
|
||||
- No phone-home without user consent
|
||||
- No premium upsell in admin notices (only on dedicated settings page)
|
||||
- All assets (CSS, JS, images) included — no external CDN
|
||||
- No minified-only JS/CSS — source files must be readable
|
||||
- Proper text domain and i18n
|
||||
- Sanitize all inputs, escape all outputs
|
||||
- Use WordPress APIs (no direct SQL without $wpdb)
|
||||
- No tracking without opt-in
|
||||
- readme.txt with proper headers, FAQ, changelog, screenshots
|
||||
|
||||
---
|
||||
|
||||
*End of IGNY8 Plugin Build Plan*
|
||||
Binary file not shown.
@@ -0,0 +1,578 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=1200">
|
||||
<title>IGNY8 Linker Module — SAG Authority Flow</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg: #0a0e1a;
|
||||
--surface: #111827;
|
||||
--surface-light: #1a2236;
|
||||
--border: #2a3654;
|
||||
--text: #e2e8f0;
|
||||
--text-muted: #94a3b8;
|
||||
--text-dim: #64748b;
|
||||
--homepage: #f59e0b;
|
||||
--hub: #3b82f6;
|
||||
--blog: #10b981;
|
||||
--product: #ec4899;
|
||||
--service: #8b5cf6;
|
||||
--term: #06b6d4;
|
||||
--category: #f97316;
|
||||
--brand: #ef4444;
|
||||
--comparison: #14b8a6;
|
||||
--vertical-up: #fbbf24;
|
||||
--vertical-down: #60a5fa;
|
||||
--sibling: #34d399;
|
||||
--cross-cluster: #f472b6;
|
||||
--taxonomy-ctx: #22d3ee;
|
||||
--breadcrumb: #a78bfa;
|
||||
--related: #fb923c;
|
||||
--ext-t1: #fcd34d;
|
||||
--ext-t2: #93c5fd;
|
||||
--ext-t3: #a5b4fc;
|
||||
--ext-t4: #86efac;
|
||||
--ext-t5: #fca5a5;
|
||||
}
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
font-family: 'Outfit', sans-serif;
|
||||
overflow-x: hidden;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.header {
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding: 14px 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: linear-gradient(180deg, var(--surface-light) 0%, var(--bg) 100%);
|
||||
}
|
||||
|
||||
.header-left { display: flex; align-items: center; gap: 14px; }
|
||||
|
||||
.logo {
|
||||
width: 36px; height: 36px; border-radius: 10px;
|
||||
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 16px; font-weight: 800; color: #fff;
|
||||
}
|
||||
|
||||
.header-title { font-size: 16px; font-weight: 700; letter-spacing: -0.3px; }
|
||||
.header-sub { font-size: 11px; color: var(--text-dim); font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
.view-toggle {
|
||||
display: flex; gap: 4px; background: var(--surface); border-radius: 8px; padding: 3px;
|
||||
}
|
||||
|
||||
.view-btn {
|
||||
padding: 6px 14px; border-radius: 6px; border: none;
|
||||
background: transparent; color: var(--text-dim);
|
||||
font-size: 11px; font-weight: 600; cursor: pointer;
|
||||
font-family: 'Outfit', sans-serif; text-transform: uppercase; letter-spacing: 0.5px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.view-btn.active {
|
||||
background: linear-gradient(135deg, #3b82f6, #6366f1); color: #fff;
|
||||
}
|
||||
|
||||
.layout { display: flex; height: calc(100vh - 65px); }
|
||||
|
||||
.sidebar {
|
||||
width: 220px; border-right: 1px solid var(--border);
|
||||
padding: 16px; overflow-y: auto; background: var(--surface);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar-label {
|
||||
font-size: 9px; font-weight: 700; color: var(--text-dim);
|
||||
letter-spacing: 1.5px; margin-bottom: 10px; margin-top: 4px;
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
display: flex; align-items: center; gap: 8px; width: 100%;
|
||||
padding: 7px 10px; margin-bottom: 3px; border-radius: 6px;
|
||||
border: 1px solid transparent; background: transparent;
|
||||
color: var(--text-muted); font-size: 10px; font-weight: 500;
|
||||
cursor: pointer; text-align: left; font-family: 'Outfit', sans-serif;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.filter-btn:hover { background: rgba(255,255,255,0.03); }
|
||||
.filter-btn.active { border-color: rgba(255,255,255,0.1); }
|
||||
|
||||
.filter-dot {
|
||||
width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0;
|
||||
}
|
||||
|
||||
.divider { height: 1px; background: var(--border); margin: 14px 0; }
|
||||
|
||||
.page-type-item {
|
||||
display: flex; align-items: center; gap: 8px; padding: 4px 10px; margin-bottom: 2px;
|
||||
}
|
||||
.page-type-dot {
|
||||
width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0;
|
||||
}
|
||||
.page-type-label { font-size: 10px; color: var(--text-muted); }
|
||||
.page-type-count { font-size: 8px; color: var(--text-dim); font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
.health-box {
|
||||
padding: 10px; border-radius: 8px; margin-top: 4px;
|
||||
}
|
||||
.health-row { display: flex; justify-content: space-between; margin-bottom: 6px; }
|
||||
.health-label { font-size: 10px; color: var(--text-muted); }
|
||||
.health-value { font-size: 12px; font-weight: 700; font-family: 'JetBrains Mono', monospace; }
|
||||
.health-bar { height: 4px; background: var(--border); border-radius: 2px; overflow: hidden; }
|
||||
.health-fill { height: 100%; border-radius: 2px; }
|
||||
|
||||
.health-stats {
|
||||
margin-top: 8px; padding: 8px 10px; border-radius: 6px;
|
||||
}
|
||||
.health-stat { font-size: 9px; color: var(--text-dim); margin-bottom: 2px; }
|
||||
.health-stat span { font-weight: 700; }
|
||||
|
||||
.canvas-area { flex: 1; position: relative; overflow: hidden; }
|
||||
|
||||
.stats-bar {
|
||||
position: absolute; top: 12px; left: 50%; transform: translateX(-50%); z-index: 10;
|
||||
display: flex; gap: 8px; background: rgba(17,24,39,0.9); border-radius: 10px;
|
||||
padding: 6px 12px; border: 1px solid var(--border); backdrop-filter: blur(8px);
|
||||
}
|
||||
.stat-item {
|
||||
text-align: center; padding: 2px 10px;
|
||||
border-right: 1px solid var(--border);
|
||||
}
|
||||
.stat-item:last-child { border-right: none; }
|
||||
.stat-value { font-size: 16px; font-weight: 800; font-family: 'JetBrains Mono', monospace; }
|
||||
.stat-label { font-size: 7px; color: var(--text-dim); letter-spacing: 0.5px; }
|
||||
|
||||
svg text { user-select: none; }
|
||||
|
||||
.link-line { transition: opacity 0.35s ease; }
|
||||
.node-group { cursor: pointer; transition: opacity 0.35s ease; }
|
||||
|
||||
@keyframes pulse-ring {
|
||||
0%, 100% { r: 58; opacity: 0.25; }
|
||||
50% { r: 66; opacity: 0.08; }
|
||||
}
|
||||
|
||||
@keyframes flow-dot {
|
||||
0% { offset-distance: 0%; opacity: 0; }
|
||||
10% { opacity: 1; }
|
||||
90% { opacity: 1; }
|
||||
100% { offset-distance: 100%; opacity: 0; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<div class="header-left">
|
||||
<div class="logo">⛓</div>
|
||||
<div>
|
||||
<div class="header-title">IGNY8 Linker Module</div>
|
||||
<div class="header-sub">SAG Authority Flow Visualization</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="view-toggle">
|
||||
<button class="view-btn active" data-view="internal">Internal</button>
|
||||
<button class="view-btn" data-view="external">External</button>
|
||||
<button class="view-btn" data-view="combined">Combined</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layout">
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar" id="sidebar"></div>
|
||||
|
||||
<!-- Canvas -->
|
||||
<div class="canvas-area">
|
||||
<div class="stats-bar" id="stats-bar"></div>
|
||||
<svg id="canvas" width="100%" height="100%" viewBox="0 0 1020 720" preserveAspectRatio="xMidYMid meet"></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
// ─── STATE ───
|
||||
let activeFilter = 'all';
|
||||
let activeView = 'internal';
|
||||
|
||||
// ─── COLORS ───
|
||||
const C = {
|
||||
homepage:'#f59e0b', hub:'#3b82f6', blog:'#10b981', product:'#ec4899',
|
||||
service:'#8b5cf6', term:'#06b6d4', category:'#f97316', brand:'#ef4444',
|
||||
comparison:'#14b8a6',
|
||||
verticalUp:'#fbbf24', verticalDown:'#60a5fa', sibling:'#34d399',
|
||||
crossCluster:'#f472b6', taxonomyCtx:'#22d3ee', breadcrumb:'#a78bfa', related:'#fb923c',
|
||||
extT1:'#fcd34d', extT2:'#93c5fd', extT3:'#a5b4fc', extT4:'#86efac', extT5:'#fca5a5',
|
||||
text:'#e2e8f0', muted:'#94a3b8', dim:'#64748b', border:'#2a3654',
|
||||
bg:'#0a0e1a', surface:'#111827'
|
||||
};
|
||||
|
||||
// ─── DATA ───
|
||||
const filters = [
|
||||
{ key:'all', label:'All Links', color: C.text },
|
||||
{ key:'vertical', label:'Vertical (Hub ↕ Blog)', color: C.verticalUp },
|
||||
{ key:'sibling', label:'Sibling (Blog ↔ Blog)', color: C.sibling },
|
||||
{ key:'cross', label:'Cross-Cluster (Hub ↔ Hub)', color: C.crossCluster },
|
||||
{ key:'taxonomy', label:'Taxonomy (Term → Hubs)', color: C.taxonomyCtx },
|
||||
{ key:'breadcrumb', label:'Breadcrumb (Structural)', color: C.breadcrumb },
|
||||
{ key:'related', label:'Related (Cross-Cluster)', color: C.related },
|
||||
];
|
||||
|
||||
const pageTypes = [
|
||||
{ type:'homepage', label:'Homepage', count:'1 page' },
|
||||
{ type:'hub', label:'Cluster Hubs', count:'12 pages' },
|
||||
{ type:'blog', label:'Blog Posts', count:'36 pages' },
|
||||
{ type:'term', label:'Term Pages', count:'24 pages' },
|
||||
{ type:'product', label:'Products', count:'50 pages' },
|
||||
{ type:'service', label:'Services', count:'6 pages' },
|
||||
{ type:'category', label:'Categories', count:'4 pages' },
|
||||
{ type:'brand', label:'Brand Pages', count:'3 pages' },
|
||||
{ type:'comparison', label:'Comparisons', count:'5 pages' },
|
||||
];
|
||||
|
||||
const nodes = [
|
||||
{ id:'home', x:500, y:95, label:'Homepage', type:'homepage', tier:'T1', info:'15 outbound', size:54 },
|
||||
{ id:'cat1', x:160, y:178, label:'Category: Foot', type:'category', info:'8 links', size:34 },
|
||||
{ id:'cat2', x:840, y:178, label:'Category: Neck', type:'category', info:'6 links', size:34 },
|
||||
{ id:'hub1', x:300, y:295, label:'Foot × Neuro', type:'hub', tier:'T2', info:'Hub · 12 links', size:46 },
|
||||
{ id:'hub2', x:500, y:198, label:'EMS × Foot', type:'hub', tier:'T2', info:'Hub · 10 links', size:44 },
|
||||
{ id:'hub3', x:700, y:295, label:'Heated × Neck', type:'hub', tier:'T3', info:'Hub · 9 links', size:42 },
|
||||
{ id:'term1', x:155, y:300, label:'Neuropathy', type:'term', info:'→ 3 hubs', size:34 },
|
||||
{ id:'term2', x:845, y:300, label:'Heated', type:'term', info:'→ 2 hubs', size:34 },
|
||||
{ id:'blog1', x:235, y:462, label:'Doctor Picks', type:'blog', tier:'T4', info:'6 links', size:32 },
|
||||
{ id:'blog2', x:330, y:430, label:'EMS vs TENS', type:'blog', tier:'T4', info:'5 links', size:32 },
|
||||
{ id:'blog3', x:395, y:478, label:'Does It Help?', type:'blog', tier:'T4', info:'4 links', size:32 },
|
||||
{ id:'blog4', x:625, y:430, label:'Best Heated', type:'blog', tier:'T4', info:'5 links', size:32 },
|
||||
{ id:'blog5', x:720, y:462, label:'Neck Pain Fix', type:'blog', tier:'T4', info:'4 links', size:32 },
|
||||
{ id:'blog6', x:575, y:478, label:'Heat Therapy', type:'blog', tier:'T4', info:'4 links', size:32 },
|
||||
{ id:'prod1', x:175, y:418, label:'RENPHO Pro', type:'product', info:'3 links', size:30 },
|
||||
{ id:'prod2', x:825, y:418, label:'Homedics Heat', type:'product', info:'3 links', size:30 },
|
||||
{ id:'comp1', x:500, y:558, label:'Brand Compare', type:'comparison', tier:'T5', info:'8 links', size:34 },
|
||||
];
|
||||
|
||||
const links = [
|
||||
// Type 1: Vertical Up — Blog → Hub (mandatory)
|
||||
{ from:'blog1', to:'hub1', type:'vertical', color:C.verticalUp, label:'MANDATORY' },
|
||||
{ from:'blog2', to:'hub1', type:'vertical', color:C.verticalUp },
|
||||
{ from:'blog3', to:'hub1', type:'vertical', color:C.verticalUp },
|
||||
{ from:'blog4', to:'hub3', type:'vertical', color:C.verticalUp, label:'MANDATORY' },
|
||||
{ from:'blog5', to:'hub3', type:'vertical', color:C.verticalUp },
|
||||
{ from:'blog6', to:'hub3', type:'vertical', color:C.verticalUp },
|
||||
// Type 2: Vertical Down — Hub → Blog/Product
|
||||
{ from:'hub1', to:'blog1', type:'vertical', color:C.verticalDown },
|
||||
{ from:'hub1', to:'blog2', type:'vertical', color:C.verticalDown },
|
||||
{ from:'hub3', to:'blog4', type:'vertical', color:C.verticalDown },
|
||||
{ from:'hub3', to:'blog5', type:'vertical', color:C.verticalDown },
|
||||
{ from:'hub1', to:'prod1', type:'vertical', color:C.verticalDown },
|
||||
{ from:'hub3', to:'prod2', type:'vertical', color:C.verticalDown },
|
||||
// Type 3: Sibling — Blog ↔ Blog
|
||||
{ from:'blog1', to:'blog2', type:'sibling', color:C.sibling, label:'MAX 2', curve:-22 },
|
||||
{ from:'blog2', to:'blog3', type:'sibling', color:C.sibling, curve:-18 },
|
||||
{ from:'blog4', to:'blog5', type:'sibling', color:C.sibling, label:'MAX 2', curve:-22 },
|
||||
// Type 4: Cross-Cluster — Hub ↔ Hub
|
||||
{ from:'hub1', to:'hub3', type:'cross', color:C.crossCluster, label:'SHARED: "Foot"', curve:35 },
|
||||
{ from:'hub1', to:'hub2', type:'cross', color:C.crossCluster, curve:20 },
|
||||
{ from:'hub2', to:'hub3', type:'cross', color:C.crossCluster, curve:20 },
|
||||
// Type 5: Taxonomy — Term → Hubs
|
||||
{ from:'term1', to:'hub1', type:'taxonomy', color:C.taxonomyCtx, label:'ALL HUBS' },
|
||||
{ from:'term1', to:'hub2', type:'taxonomy', color:C.taxonomyCtx },
|
||||
{ from:'term2', to:'hub3', type:'taxonomy', color:C.taxonomyCtx, label:'ALL HUBS' },
|
||||
{ from:'term2', to:'hub2', type:'taxonomy', color:C.taxonomyCtx },
|
||||
// Type 6: Breadcrumb
|
||||
{ from:'home', to:'hub1', type:'breadcrumb', color:C.breadcrumb },
|
||||
{ from:'home', to:'hub2', type:'breadcrumb', color:C.breadcrumb },
|
||||
{ from:'home', to:'hub3', type:'breadcrumb', color:C.breadcrumb },
|
||||
{ from:'home', to:'cat1', type:'breadcrumb', color:C.breadcrumb },
|
||||
{ from:'home', to:'cat2', type:'breadcrumb', color:C.breadcrumb },
|
||||
// Type 7: Related (cross-cluster blogs)
|
||||
{ from:'blog3', to:'blog4', type:'related', color:C.related, label:'CROSS-CLUSTER', curve:25 },
|
||||
{ from:'blog6', to:'blog2', type:'related', color:C.related, curve:-25 },
|
||||
];
|
||||
|
||||
const externalLinks = [
|
||||
{ target:'home', count:'10-30', dr:'30-60', tier:'T1', color:C.extT1, ox:-70, oy:-50 },
|
||||
{ target:'hub1', count:'5-15', dr:'25-50', tier:'T2', color:C.extT2, ox:-75, oy:-45 },
|
||||
{ target:'hub2', count:'5-15', dr:'25-50', tier:'T2', color:C.extT2, ox:-70, oy:-50 },
|
||||
{ target:'hub3', count:'5-15', dr:'25-50', tier:'T2', color:C.extT2, ox:75, oy:-45 },
|
||||
{ target:'blog1', count:'1-2', dr:'20-35', tier:'T4', color:C.extT4, ox:-55, oy:-35 },
|
||||
{ target:'comp1', count:'2-6', dr:'25-40', tier:'T5', color:C.extT5, ox:-70, oy:-45 },
|
||||
];
|
||||
|
||||
// ─── HELPERS ───
|
||||
function nodeById(id) { return nodes.find(n => n.id === id); }
|
||||
|
||||
function svgEl(tag, attrs, parent) {
|
||||
const el = document.createElementNS('http://www.w3.org/2000/svg', tag);
|
||||
for (const [k, v] of Object.entries(attrs || {})) {
|
||||
if (k === 'textContent') el.textContent = v;
|
||||
else el.setAttribute(k, v);
|
||||
}
|
||||
if (parent) parent.appendChild(el);
|
||||
return el;
|
||||
}
|
||||
|
||||
function isVisible(linkType) {
|
||||
if (activeFilter === 'all') return true;
|
||||
return linkType === activeFilter;
|
||||
}
|
||||
|
||||
function curvePath(x1, y1, x2, y2, curveAmt) {
|
||||
if (!curveAmt) return `M${x1},${y1} L${x2},${y2}`;
|
||||
const dx = x2 - x1, dy = y2 - y1;
|
||||
const len = Math.sqrt(dx*dx + dy*dy) || 1;
|
||||
const mx = (x1+x2)/2, my = (y1+y2)/2;
|
||||
const cx = mx + (dy/len)*curveAmt;
|
||||
const cy = my - (dx/len)*curveAmt;
|
||||
return `M${x1},${y1} Q${cx},${cy} ${x2},${y2}`;
|
||||
}
|
||||
|
||||
// ─── RENDER SIDEBAR ───
|
||||
function renderSidebar() {
|
||||
const sb = document.getElementById('sidebar');
|
||||
sb.innerHTML = '';
|
||||
|
||||
// Link type filters
|
||||
const l1 = document.createElement('div'); l1.className = 'sidebar-label'; l1.textContent = 'LINK TYPES'; sb.appendChild(l1);
|
||||
filters.forEach(f => {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'filter-btn' + (activeFilter === f.key ? ' active' : '');
|
||||
btn.style.borderColor = activeFilter === f.key ? f.color + '40' : 'transparent';
|
||||
btn.style.background = activeFilter === f.key ? f.color + '12' : 'transparent';
|
||||
btn.style.color = activeFilter === f.key ? f.color : '';
|
||||
btn.innerHTML = `<div class="filter-dot" style="background:${f.color}"></div>${f.label}`;
|
||||
btn.onclick = () => { activeFilter = activeFilter === f.key ? 'all' : f.key; render(); };
|
||||
sb.appendChild(btn);
|
||||
});
|
||||
|
||||
// Divider
|
||||
sb.appendChild(Object.assign(document.createElement('div'), { className: 'divider' }));
|
||||
|
||||
// Page types
|
||||
const l2 = document.createElement('div'); l2.className = 'sidebar-label'; l2.textContent = 'PAGE TYPES'; sb.appendChild(l2);
|
||||
pageTypes.forEach(p => {
|
||||
const d = document.createElement('div'); d.className = 'page-type-item';
|
||||
d.innerHTML = `<div class="page-type-dot" style="background:${C[p.type]}40;border:1.5px solid ${C[p.type]}"></div>
|
||||
<div><div class="page-type-label">${p.label}</div><div class="page-type-count">${p.count}</div></div>`;
|
||||
sb.appendChild(d);
|
||||
});
|
||||
|
||||
sb.appendChild(Object.assign(document.createElement('div'), { className: 'divider' }));
|
||||
|
||||
// Health
|
||||
const l3 = document.createElement('div'); l3.className = 'sidebar-label'; l3.textContent = 'HEALTH'; sb.appendChild(l3);
|
||||
|
||||
const hbox = document.createElement('div'); hbox.className = 'health-box';
|
||||
hbox.style.background = C.hub + '08'; hbox.style.border = `1px solid ${C.hub}20`;
|
||||
hbox.innerHTML = `
|
||||
<div class="health-row"><span class="health-label">Link Coverage</span><span class="health-value" style="color:${C.hub}">87/100</span></div>
|
||||
<div class="health-bar"><div class="health-fill" style="width:87%;background:linear-gradient(90deg,${C.hub},${C.term})"></div></div>`;
|
||||
sb.appendChild(hbox);
|
||||
|
||||
const hs = document.createElement('div'); hs.className = 'health-stats';
|
||||
hs.style.background = C.sibling + '08';
|
||||
hs.innerHTML = `
|
||||
<div class="health-stat">Orphan Pages: <span style="color:#ef4444">0</span></div>
|
||||
<div class="health-stat">Broken Links: <span style="color:#ef4444">2</span></div>
|
||||
<div class="health-stat">Over-linked: <span style="color:${C.homepage}">1</span></div>
|
||||
<div class="health-stat">Avg Links/Page: <span style="color:${C.hub}">6.2</span></div>`;
|
||||
sb.appendChild(hs);
|
||||
}
|
||||
|
||||
// ─── RENDER STATS BAR ───
|
||||
function renderStats() {
|
||||
const bar = document.getElementById('stats-bar');
|
||||
const stats = [
|
||||
{ value:'215', label:'Total Links', color:C.hub },
|
||||
{ value:'141', label:'Internal', color:C.sibling },
|
||||
{ value:'83', label:'External', color:C.crossCluster },
|
||||
{ value:'7', label:'Link Types', color:C.term },
|
||||
{ value:'0', label:'Orphans', color:C.sibling },
|
||||
];
|
||||
bar.innerHTML = stats.map((s,i) =>
|
||||
`<div class="stat-item" ${i===stats.length-1?'style="border-right:none"':''}>
|
||||
<div class="stat-value" style="color:${s.color}">${s.value}</div>
|
||||
<div class="stat-label">${s.label}</div>
|
||||
</div>`
|
||||
).join('');
|
||||
}
|
||||
|
||||
// ─── RENDER SVG CANVAS ───
|
||||
function renderCanvas() {
|
||||
const svg = document.getElementById('canvas');
|
||||
svg.innerHTML = '';
|
||||
|
||||
// Defs
|
||||
const defs = svgEl('defs', {}, svg);
|
||||
defs.innerHTML = `
|
||||
<marker id="ah" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
|
||||
<polygon points="0 0, 8 3, 0 6" fill="${C.dim}"/>
|
||||
</marker>
|
||||
<radialGradient id="glow-c" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" stop-color="${C.homepage}12"/><stop offset="100%" stop-color="transparent"/>
|
||||
</radialGradient>`;
|
||||
|
||||
// Background glow + rings
|
||||
svgEl('circle', { cx:500, cy:330, r:300, fill:'url(#glow-c)' }, svg);
|
||||
[80,150,220,290,360].forEach(r => svgEl('circle', { cx:500, cy:330, r, fill:'none', stroke:C.border+'28', 'stroke-width':'0.5', 'stroke-dasharray':'4,8' }, svg));
|
||||
|
||||
// Cluster boundaries
|
||||
const clG = svgEl('g', { opacity:'0.5' }, svg);
|
||||
svgEl('rect', { x:185, y:255, width:270, height:265, rx:16, fill:'none', stroke:C.hub+'20', 'stroke-width':'1', 'stroke-dasharray':'6,4' }, clG);
|
||||
svgEl('text', { x:195, y:272, fill:C.hub+'35', 'font-size':'8', 'font-family':"'JetBrains Mono', monospace", textContent:'CLUSTER: Foot × Neuropathy' }, clG);
|
||||
svgEl('rect', { x:535, y:255, width:270, height:265, rx:16, fill:'none', stroke:C.hub+'20', 'stroke-width':'1', 'stroke-dasharray':'6,4' }, clG);
|
||||
svgEl('text', { x:545, y:272, fill:C.hub+'35', 'font-size':'8', 'font-family':"'JetBrains Mono', monospace", textContent:'CLUSTER: Heated × Neck' }, clG);
|
||||
|
||||
// ─── DRAW LINKS ───
|
||||
const linkGroup = svgEl('g', { id:'link-layer' }, svg);
|
||||
|
||||
if (activeView === 'internal' || activeView === 'combined') {
|
||||
links.forEach(lk => {
|
||||
const from = nodeById(lk.from), to = nodeById(lk.to);
|
||||
if (!from || !to) return;
|
||||
const vis = isVisible(lk.type);
|
||||
const g = svgEl('g', { class:'link-line', opacity: vis ? '0.75' : '0.05' }, linkGroup);
|
||||
const dash = lk.type === 'breadcrumb' ? '4,4' : lk.type === 'related' ? '8,4' : 'none';
|
||||
const path = curvePath(from.x, from.y, to.x, to.y, lk.curve || (lk.type==='cross'?30 : 0));
|
||||
const pathId = 'p-' + lk.from + '-' + lk.to;
|
||||
svgEl('path', { id: pathId, d: path, fill:'none', stroke: lk.color, 'stroke-width': vis && activeFilter !== 'all' ? '2.2' : '1.2', 'stroke-dasharray': dash }, g);
|
||||
|
||||
// Animated dot for active filter
|
||||
if (vis && activeFilter !== 'all') {
|
||||
const dot = svgEl('circle', { r:'3', fill: lk.color, opacity:'0.9' }, g);
|
||||
const anim = svgEl('animateMotion', { dur: '2.5s', repeatCount:'indefinite' }, dot);
|
||||
svgEl('mpath', { href: '#'+pathId }, anim);
|
||||
}
|
||||
|
||||
// Label
|
||||
if (lk.label && vis) {
|
||||
const mx = (from.x + to.x) / 2, my = (from.y + to.y) / 2;
|
||||
const dx = to.x-from.x, dy = to.y-from.y, len = Math.sqrt(dx*dx+dy*dy)||1;
|
||||
const off = lk.curve || (lk.type==='cross'?30:0);
|
||||
const cx = mx + (dy/len)*off*0.5, cy = my - (dx/len)*off*0.5;
|
||||
svgEl('rect', { x:cx-38, y:cy-9, width:76, height:15, rx:3, fill:C.bg, stroke:lk.color+'35', 'stroke-width':'0.5' }, g);
|
||||
svgEl('text', { x:cx, y:cy+2, 'text-anchor':'middle', fill:lk.color+'cc', 'font-size':'7', 'font-family':"'JetBrains Mono', monospace", textContent: lk.label }, g);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ─── EXTERNAL LINKS ───
|
||||
if (activeView === 'external' || activeView === 'combined') {
|
||||
const extG = svgEl('g', { id:'ext-layer' }, svg);
|
||||
externalLinks.forEach(el => {
|
||||
const n = nodeById(el.target);
|
||||
if (!n) return;
|
||||
const sx = n.x + el.ox, sy = n.y + el.oy;
|
||||
const ex = n.x + (el.ox > 0 ? 12 : -12) * (Math.abs(el.ox)/el.ox || 1);
|
||||
const ey = n.y - 5;
|
||||
const g = svgEl('g', {}, extG);
|
||||
svgEl('line', { x1:sx, y1:sy, x2:n.x + (el.ox>0?10:-10), y2:n.y-8, stroke:el.color, 'stroke-width':'2', 'marker-end':'url(#ah)' }, g);
|
||||
svgEl('rect', { x:sx-30, y:sy-18, width:60, height:26, rx:4, fill:el.color+'18', stroke:el.color+'45', 'stroke-width':'1' }, g);
|
||||
svgEl('text', { x:sx, y:sy-6, 'text-anchor':'middle', fill:el.color, 'font-size':'8', 'font-weight':'600', 'font-family':"'JetBrains Mono', monospace", textContent: el.count+' links' }, g);
|
||||
svgEl('text', { x:sx, y:sy+5, 'text-anchor':'middle', fill:C.dim, 'font-size':'7', 'font-family':"'JetBrains Mono', monospace", textContent: 'DR '+el.dr }, g);
|
||||
svgEl('text', { x:sx, y:sy-22, 'text-anchor':'middle', fill:el.color+'90', 'font-size':'7', 'font-weight':'700', 'font-family':"'JetBrains Mono', monospace", textContent: el.tier+' EXTERNAL' }, g);
|
||||
});
|
||||
|
||||
// Authority flow label
|
||||
svgEl('text', { x:430, y:155, 'text-anchor':'middle', fill:C.homepage+'45', 'font-size':'8', 'font-family':"'JetBrains Mono', monospace", textContent:'AUTHORITY FLOWS DOWN ▼', transform:'rotate(-12 430 155)' }, extG);
|
||||
svgEl('text', { x:500, y:395, 'text-anchor':'middle', fill:C.verticalUp+'35', 'font-size':'8', 'font-family':"'JetBrains Mono', monospace", textContent:'▲ AUTHORITY FLOWS UP' }, extG);
|
||||
}
|
||||
|
||||
// ─── DRAW NODES ───
|
||||
const nodeLayer = svgEl('g', { id:'node-layer' }, svg);
|
||||
nodes.forEach(n => {
|
||||
const col = C[n.type] || '#666';
|
||||
const sz = n.size || 36;
|
||||
const g = svgEl('g', { class:'node-group' }, nodeLayer);
|
||||
|
||||
// Outer ring
|
||||
svgEl('circle', { cx:n.x, cy:n.y, r:sz, fill:col+'15', stroke:col+'55', 'stroke-width':'1.5' }, g);
|
||||
svgEl('circle', { cx:n.x, cy:n.y, r:sz-5, fill:col+'08', stroke:'none' }, g);
|
||||
|
||||
// Tier badge
|
||||
if (n.tier) {
|
||||
svgEl('rect', { x:n.x+sz*0.48, y:n.y-sz+1, width:28, height:16, rx:8, fill:col }, g);
|
||||
svgEl('text', { x:n.x+sz*0.48+14, y:n.y-sz+12.5, 'text-anchor':'middle', fill:'#000', 'font-size':'9', 'font-weight':'700', 'font-family':"'JetBrains Mono', monospace", textContent:n.tier }, g);
|
||||
}
|
||||
|
||||
// Labels
|
||||
const lbl = n.label.length > 15 ? n.label.slice(0,14)+'…' : n.label;
|
||||
svgEl('text', { x:n.x, y:n.y-4, 'text-anchor':'middle', fill:C.text, 'font-size':'10.5', 'font-weight':'600', 'font-family':"'Outfit', sans-serif", textContent:lbl }, g);
|
||||
svgEl('text', { x:n.x, y:n.y+10, 'text-anchor':'middle', fill:C.muted, 'font-size':'8', 'font-family':"'JetBrains Mono', monospace", textContent:n.type.toUpperCase() }, g);
|
||||
if (n.info) {
|
||||
svgEl('text', { x:n.x, y:n.y+22, 'text-anchor':'middle', fill:C.dim, 'font-size':'7.5', 'font-family':"'JetBrains Mono', monospace", textContent:n.info }, g);
|
||||
}
|
||||
});
|
||||
|
||||
// ─── LEGENDS ───
|
||||
const legG = svgEl('g', {}, svg);
|
||||
|
||||
// Internal legend
|
||||
const iLeg = [
|
||||
{ color:C.verticalUp, label:'Blog → Hub (mandatory)' },
|
||||
{ color:C.verticalDown, label:'Hub → Blog / Product' },
|
||||
{ color:C.sibling, label:'Blog ↔ Blog (max 2)' },
|
||||
{ color:C.crossCluster, label:'Hub ↔ Hub (shared attr)' },
|
||||
{ color:C.taxonomyCtx, label:'Term → All Connected Hubs' },
|
||||
{ color:C.breadcrumb, label:'Breadcrumb (structural)', dash:'4,4' },
|
||||
{ color:C.related, label:'Related (cross-cluster)', dash:'8,4' },
|
||||
];
|
||||
svgEl('text', { x:30, y:562, fill:C.muted, 'font-size':'9', 'font-weight':'700', 'font-family':"'Outfit', sans-serif", 'letter-spacing':'1.5', textContent:'INTERNAL LINKS' }, legG);
|
||||
iLeg.forEach((it, i) => {
|
||||
svgEl('line', { x1:30, y1:578+i*17, x2:48, y2:578+i*17, stroke:it.color, 'stroke-width':'2', 'stroke-dasharray': it.dash||'none' }, legG);
|
||||
svgEl('text', { x:56, y:582+i*17, fill:C.dim, 'font-size':'8.5', 'font-family':"'JetBrains Mono', monospace", textContent:it.label }, legG);
|
||||
});
|
||||
|
||||
// External legend (when visible)
|
||||
if (activeView === 'external' || activeView === 'combined') {
|
||||
const eLeg = [
|
||||
{ color:C.extT1, label:'T1 → Homepage (10-30)' },
|
||||
{ color:C.extT2, label:'T2 → Top Hubs (5-15)' },
|
||||
{ color:C.extT3, label:'T3 → Other Hubs (3-10)' },
|
||||
{ color:C.extT4, label:'T4 → Select Blogs (1-4)' },
|
||||
{ color:C.extT5, label:'T5 → Auth Magnets (2-6)' },
|
||||
];
|
||||
svgEl('text', { x:800, y:562, fill:C.muted, 'font-size':'9', 'font-weight':'700', 'font-family':"'Outfit', sans-serif", 'letter-spacing':'1.5', textContent:'EXTERNAL LINKS' }, legG);
|
||||
eLeg.forEach((it, i) => {
|
||||
svgEl('line', { x1:800, y1:578+i*17, x2:818, y2:578+i*17, stroke:it.color, 'stroke-width':'2' }, legG);
|
||||
svgEl('text', { x:826, y:582+i*17, fill:C.dim, 'font-size':'8.5', 'font-family':"'JetBrains Mono', monospace", textContent:it.label }, legG);
|
||||
});
|
||||
}
|
||||
|
||||
// Density rule box
|
||||
svgEl('rect', { x:370, y:622, width:260, height:42, rx:8, fill:C.surface, stroke:C.border, 'stroke-width':'1' }, svg);
|
||||
svgEl('text', { x:500, y:639, 'text-anchor':'middle', fill:C.muted, 'font-size':'9', 'font-weight':'600', 'font-family':"'Outfit', sans-serif", textContent:'DENSITY RULE' }, svg);
|
||||
svgEl('text', { x:500, y:653, 'text-anchor':'middle', fill:C.dim, 'font-size':'7.5', 'font-family':"'JetBrains Mono', monospace", textContent:'1-2 links per 300 words · No orphans · Max 8 words/anchor' }, svg);
|
||||
}
|
||||
|
||||
// ─── VIEW TOGGLE ───
|
||||
document.querySelectorAll('.view-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.view-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
activeView = btn.dataset.view;
|
||||
render();
|
||||
});
|
||||
});
|
||||
|
||||
// ─── RENDER ALL ───
|
||||
function render() {
|
||||
renderSidebar();
|
||||
renderStats();
|
||||
renderCanvas();
|
||||
}
|
||||
|
||||
render();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
@@ -0,0 +1,541 @@
|
||||
# Document 3 — SAG Interlinking Specification (Linker Module)
|
||||
|
||||
## Detailed Section Plan
|
||||
|
||||
**Version:** 1.0 | March 2026
|
||||
**Status:** Plan — Ready for section-by-section build
|
||||
**Dependency:** SAG-IGNY8-Implementation.md (Section 14 pipeline, Section 16 data models, blueprint JSON)
|
||||
**Target Format:** Markdown (.md) for IGNY8 repo use with Claude Code
|
||||
**Estimated Length:** ~800-1,000 lines
|
||||
|
||||
---
|
||||
|
||||
## Current State Summary (inputs to this document)
|
||||
|
||||
### What Exists in IGNY8 Today
|
||||
- **Linker module:** Backend at `business/linking/`, API at `modules/linker/`, frontend at `pages/Linker/` and `api/linker.api.ts` — all INACTIVE behind `linker_enabled` feature flag
|
||||
- **Existing Linker capability** (pre-SAG): Finds link candidates based on content similarity, injects links with varied anchor text, configurable link density limits
|
||||
- **Blueprint JSON** already has `internal_linking_map` field (currently `{"rules_reference": "SAG-Interlinking-Specification.md"}` — pointing to THIS document), `linked_attribute_terms` per cluster, `cross_cluster_links` per cluster, and `link_coverage_score` on SAGCluster model
|
||||
- **Content model** has `sag_cluster_id` field (planned) — links content back to its cluster for linking rules
|
||||
- **Pipeline Stage 7** (SAG-enhanced): "Pre-computed internal links ready" at review queue — means links are generated BEFORE publish, not after
|
||||
|
||||
### What SAG-IGNY8-Implementation.md Already Defines
|
||||
- Page types: Blog Post, Cluster Hub Page, Product Page, Service Page, Category Page, Attribute Term Page, Brand Page, Comparison Page
|
||||
- Cluster types: Product/Service Category, Condition/Problem, Feature, Brand, Informational, Comparison — each has different hub page style
|
||||
- Blueprint stores `linked_attribute_terms` (which taxonomy terms a cluster connects to) and `cross_cluster_links` (which other clusters share attribute values)
|
||||
- Execution priority: Phase 1 = category pages + top hubs, Phase 2 = remaining hubs + first blogs, Phase 3 = attribute term pages, Phase 4 = additional blogs + brand comparisons
|
||||
- Health monitoring already tracks "internal link coverage" as one of the weekly health check items
|
||||
|
||||
### What the Niche Definition Process (Doc 2) Defines
|
||||
- Each cluster has 1 hub page + 3-8 supporting content pieces
|
||||
- Clusters form at 2+ attribute value intersections — two clusters sharing an attribute value are cross-link candidates
|
||||
- Max 50 clusters per sector, backlink campaigns target top 25-30 — the other 20-25 rank purely through internal authority flow
|
||||
|
||||
### What Content Types Plan Defines
|
||||
- Taxonomy landing pages include "key subtopics + internal links" and "internal links to related clusters" as default sections
|
||||
- Cluster hub pages aggregate related terms + posts + products
|
||||
|
||||
### What the Taxonomy Term Content Plan Defines
|
||||
- Term pages need "internal links to related clusters" as a standard section
|
||||
- Cluster Hub Manager handles "cluster landing pages and cross-links"
|
||||
|
||||
---
|
||||
|
||||
## Section Plan
|
||||
|
||||
### Section 1: Purpose & Scope
|
||||
|
||||
**Content:**
|
||||
- Why SAG interlinking is fundamentally different from generic internal linking tools
|
||||
- Generic linkers scan content for keyword matches and insert links randomly — SAG linking follows deterministic rules derived from the dimensional structure
|
||||
- Every link has a structural purpose: it flows authority from backlinked pages down through the hierarchy and connects dimensionally-related content
|
||||
- This document is the rules engine specification — it tells the IGNY8 Linker module exactly what links to create, where, with what anchor text, and in what priority order
|
||||
- Scope: WordPress implementation first, platform-agnostic rules that translate to any CMS
|
||||
- Dependency: Requires an active SAG Blueprint with populated clusters, published content, and WordPress taxonomies created
|
||||
|
||||
**Inputs from existing docs:** SAG-IGNY8-Implementation.md Section 14.1 (Post-Publish → "Linker creates SAG-compliant internal links")
|
||||
|
||||
---
|
||||
|
||||
### Section 2: Page Types in the Link Graph
|
||||
|
||||
**Content:**
|
||||
Define every page type that participates in the link graph, its role, and its WordPress implementation. Each type has different linking behavior.
|
||||
|
||||
| Page Type | SAG Role | WordPress Implementation | Link Behavior |
|
||||
|-----------|----------|------------------------|---------------|
|
||||
| Homepage | T1 — authority entry point | Front page | Links to sector landing pages and top cluster hubs |
|
||||
| Sector Landing Page | Sector overview | Page (or custom page template) | Links to all cluster hubs within sector |
|
||||
| Cluster Hub Page | T2/T3 — authority distribution node | Page with hub template | Links DOWN to supporting content, ACROSS to related cluster hubs, UP to sector landing |
|
||||
| Supporting Blog Post | T4 — content depth | Post | Links UP to its cluster hub (mandatory), ACROSS to sibling blogs in same cluster, ACROSS to related cluster hubs |
|
||||
| Attribute Term Page | Taxonomy node connecting clusters | Custom taxonomy term archive with rich content | Links to ALL cluster hubs that use this attribute value |
|
||||
| Product Page | Commercial page | WooCommerce product | Links to its cluster hub, to relevant attribute term pages |
|
||||
| Service Page | Commercial page | Page with service template | Links to its cluster hub, to relevant attribute term pages |
|
||||
| Category Page | Top-level grouping | Category archive with rich content | Links to cluster hubs within this category |
|
||||
| Brand Page | Brand overview | Post or page | Links to cluster hubs featuring this brand |
|
||||
| Comparison Page | Decision-stage content | Post | Links to both compared cluster hubs |
|
||||
|
||||
**Key rule:** Every page except homepage must link to at least ONE cluster hub. No orphan pages in a SAG site.
|
||||
|
||||
**Inputs from existing docs:** SAG-IGNY8-Implementation.md Section 11.2 (content type table), Section 12.2 (platform mapping table), Content_Types_Writing_Plan.md Section 2
|
||||
|
||||
---
|
||||
|
||||
### Section 3: Link Relationship Types
|
||||
|
||||
**Content:**
|
||||
Define the 7 directional link types the system generates. Each has specific rules.
|
||||
|
||||
**Type 1: Vertical Upward (Supporting → Hub)**
|
||||
- Every supporting blog post MUST link to its cluster hub page
|
||||
- This is mandatory, not optional — enforced at content generation time
|
||||
- Anchor text uses cluster's primary keyword or hub page title variant
|
||||
- Placement: First mention of cluster topic in content body, ideally within first 2 paragraphs
|
||||
- Count: Exactly 1 link to own hub per supporting article
|
||||
|
||||
**Type 2: Vertical Downward (Hub → Supporting)**
|
||||
- Every cluster hub page links to ALL its published supporting content
|
||||
- Placement: Hub pages have a structured "Related Articles" or "In This Guide" section
|
||||
- Plus contextual in-body links where naturally relevant
|
||||
- Anchor text: Article title or primary keyword of the supporting piece
|
||||
|
||||
**Type 3: Horizontal Sibling (Supporting ↔ Supporting within same cluster)**
|
||||
- Supporting articles within the same cluster link to each other where topically relevant
|
||||
- Not mandatory for every pair — only where semantic overlap creates a natural link opportunity
|
||||
- Maximum 2 sibling links per article to avoid link dilution
|
||||
- Anchor text: Natural descriptive phrases, varied per link
|
||||
|
||||
**Type 4: Cross-Cluster (Hub ↔ Hub sharing attribute value)**
|
||||
- Two cluster hubs that share an attribute value are cross-link candidates
|
||||
- Example: "Foot × Neuropathy" and "Foot × EMS" both have Target Area = Foot → cross-link
|
||||
- Maximum 2 cross-cluster links per hub page to avoid diluting the hub's primary focus
|
||||
- Selection: Highest-value cross-links chosen by shared keyword volume overlap
|
||||
- Anchor text: The linked hub's primary keyword or a natural variant
|
||||
|
||||
**Type 5: Taxonomy Contextual (Term Page → Cluster Hubs)**
|
||||
- Each attribute term page links to EVERY cluster hub that uses that attribute value
|
||||
- Example: "Neuropathy" term page links to "Foot × Neuropathy", "EMS × Neuropathy", "Heated × Neuropathy"
|
||||
- This is the dimensional connecting layer — term pages are the linking nodes of the grid
|
||||
- Anchor text: Hub page title or cluster primary keyword
|
||||
|
||||
**Type 6: Breadcrumb Structural**
|
||||
- Every page has a breadcrumb path: Home → Sector → [Attribute Term or Category] → Hub → Current Page
|
||||
- These are navigational links, always present in page template
|
||||
- Not counted toward content link density limits
|
||||
|
||||
**Type 7: Related Content (Cross-Cluster, Semantic)**
|
||||
- For supporting blogs, a "Related Reading" or "You May Also Like" section with 2-3 links to content in OTHER clusters
|
||||
- Selected by: shared attribute values (not same cluster), complementary topics, user journey logic
|
||||
- This is the weakest link type — lowest priority, most likely to be omitted if link density cap is reached
|
||||
|
||||
**Inputs from existing docs:** Blueprint JSON `linked_attribute_terms` field (Type 5), `cross_cluster_links` field (Type 4), Taxonomy_Term_Content_Plan.md Section 7 item 5 ("internal links to related clusters")
|
||||
|
||||
---
|
||||
|
||||
### Section 4: Authority Flow Model
|
||||
|
||||
**Content:**
|
||||
How external backlink authority distributes through the SAG structure via internal links. This is the mechanism behind the "compounding authority effect."
|
||||
|
||||
**Flow path:**
|
||||
1. External backlinks hit homepage (T1) and top 25-30 cluster hub pages (T2/T3)
|
||||
2. Hub pages distribute authority DOWN to 3-8 supporting articles each
|
||||
3. Supporting articles link BACK UP to hub (reinforcing) and ACROSS to siblings (spreading)
|
||||
4. Attribute term pages act as horizontal connectors — they link to ALL hubs sharing that attribute value, creating cross-cluster authority flow
|
||||
5. Clusters WITHOUT direct backlinks receive authority through: cross-cluster links from backlinked hubs, term page connections from shared attribute values, and sibling blog cross-references
|
||||
|
||||
**Why this compounds:**
|
||||
- Every new piece of content in a cluster strengthens the hub (more upward links)
|
||||
- Every new cluster that shares an attribute value strengthens the term page (more hub links feeding into it)
|
||||
- The term page then distributes that combined authority to ALL connected hubs
|
||||
- Result: A site at DR 29 can dominate country-level rankings for thousands of queries because the internal structure amplifies whatever external authority exists
|
||||
|
||||
**Maximum hop distance:** Any page should be reachable from a backlinked page within 3 link hops. If a page requires 4+ hops, it needs a direct cross-link from a higher-authority page.
|
||||
|
||||
**Visualization:** Include a flow diagram showing Homepage → Sector → Hubs (backlinked) → Supporting Content → Term Pages → Other Hubs (not backlinked) with authority flow arrows
|
||||
|
||||
**Inputs from existing docs:** Transcript discussion of T1-T5 tier system, SAG-IGNY8-Implementation.md Section 14.3 (health monitoring tracks link coverage), SAG compounding authority evidence from MassagerSmart (DR 29 dominating country rankings)
|
||||
|
||||
---
|
||||
|
||||
### Section 5: Link Scoring & Priority Algorithm
|
||||
|
||||
**Content:**
|
||||
When the Linker has multiple potential links to create (especially for cross-cluster and related content links), it needs a scoring system to select the highest-value links.
|
||||
|
||||
**Scoring factors:**
|
||||
|
||||
| Factor | Weight | Logic |
|
||||
|--------|--------|-------|
|
||||
| Shared attribute values | 40% | More shared values = stronger topical relevance |
|
||||
| Target page authority | 25% | Pages with backlinks or higher link_coverage_score get priority |
|
||||
| Keyword overlap | 20% | Cluster keyword lists compared — higher overlap = more relevant link |
|
||||
| Content recency | 10% | Newer content gets slight priority to accelerate indexing |
|
||||
| Current link count gap | 5% | Pages below minimum inbound links get priority |
|
||||
|
||||
**Priority ordering for link creation:**
|
||||
1. Mandatory links first (Type 1: supporting → hub — always created)
|
||||
2. Hub → supporting links (Type 2 — always created for published content)
|
||||
3. Term page → hub links (Type 5 — always created)
|
||||
4. Cross-cluster hub links (Type 4 — top 2 by score)
|
||||
5. Sibling links (Type 3 — top 2 by score)
|
||||
6. Related content links (Type 7 — fill remaining capacity)
|
||||
|
||||
**Inputs from existing docs:** SAGCluster model has `link_coverage_score` field, blueprint health monitoring tracks internal link coverage
|
||||
|
||||
---
|
||||
|
||||
### Section 6: Anchor Text Generation Rules
|
||||
|
||||
**Content:**
|
||||
Anchor text strategy per link type to avoid over-optimization while maximizing keyword relevance.
|
||||
|
||||
| Link Type | Anchor Text Strategy | Examples |
|
||||
|-----------|---------------------|----------|
|
||||
| Supporting → Hub | Primary keyword of hub (60%), hub title variant (30%), natural phrase (10%) | "foot massagers for neuropathy", "our neuropathy foot massager guide", "learn more about neuropathy relief" |
|
||||
| Hub → Supporting | Article title (70%), primary keyword (20%), descriptive (10%) | "Doctor-Recommended Foot Massagers for Neuropathy", "doctor-recommended neuropathy massagers" |
|
||||
| Sibling → Sibling | Natural contextual phrase (60%), article keyword (30%), generic (10%) | "comparing EMS and TENS therapy", "EMS vs TENS for neuropathy" |
|
||||
| Cross-Cluster Hub → Hub | Target hub primary keyword (50%), descriptive (40%), generic (10%) | "EMS foot massagers", "explore our EMS foot massager guide" |
|
||||
| Term Page → Hub | Hub primary keyword (50%), hub title (40%), descriptive (10%) | "best foot massagers for neuropathy", "Foot Massagers for Neuropathy Guide" |
|
||||
| Breadcrumb | Page title (100%) | Always the page title — no variation |
|
||||
| Related Content | Natural phrase (80%), generic (20%) | "you might also find this helpful", "related: heated massagers for circulation" |
|
||||
|
||||
**Hard rules:**
|
||||
- No exact-match anchor text used more than 3 times across the entire site for the same target URL
|
||||
- Anchor text must be grammatically natural in context — never force a keyword phrase that breaks sentence flow
|
||||
- Never use "click here", "read more", or "this article" as anchor text
|
||||
- Maximum anchor text length: 8 words
|
||||
- Minimum anchor text length: 2 words
|
||||
|
||||
---
|
||||
|
||||
### Section 7: Link Density Enforcement
|
||||
|
||||
**Content:**
|
||||
Maximum and minimum outbound/inbound link counts per page type to prevent over-linking or under-linking.
|
||||
|
||||
| Page Type | Min Outbound | Max Outbound | Min Inbound | Notes |
|
||||
|-----------|-------------|-------------|-------------|-------|
|
||||
| Homepage | 5 | 15 | N/A (external) | Links to top hubs + sector pages |
|
||||
| Cluster Hub | 5 | 20 | 3 | Must link to all supporting + 2 cross-cluster |
|
||||
| Supporting Blog (<1000 words) | 2 | 5 | 1 | Must include hub link |
|
||||
| Supporting Blog (1000-2000 words) | 3 | 8 | 1 | Must include hub link |
|
||||
| Supporting Blog (2000+ words) | 4 | 12 | 1 | Must include hub link |
|
||||
| Attribute Term Page | 3 | unlimited | 0 | Links to ALL connected hubs (no cap) |
|
||||
| Product Page | 2 | 5 | 1 | Hub + relevant term pages |
|
||||
| Service Page | 2 | 5 | 1 | Hub + relevant term pages |
|
||||
|
||||
**Override logic:**
|
||||
- If a hub has 10+ supporting articles, max outbound for hub increases to 25 (listing them all adds value)
|
||||
- If content is a mega-guide (3000+ words), max outbound increases to 15
|
||||
- User can manually override density limits per page in IGNY8 UI
|
||||
|
||||
**Density ratio:** Outbound links per 300 words of content, with a target of 1-2 links per 300 words for body content. Navigational sections (related articles, breadcrumbs) don't count toward this ratio.
|
||||
|
||||
---
|
||||
|
||||
### Section 8: Cross-Cluster & Cross-Sector Linking Logic
|
||||
|
||||
**Content:**
|
||||
Detailed rules for when and how to create links between clusters.
|
||||
|
||||
**Cross-cluster within same sector:**
|
||||
- Two clusters are cross-link candidates when they share at least 1 attribute value
|
||||
- Example: "Foot × Neuropathy" and "Foot × Plantar Fasciitis" share Target Area = Foot
|
||||
- The Linker checks `attribute_intersection` JSON of both clusters for shared values
|
||||
- Maximum 2 cross-cluster outbound links per hub page
|
||||
- Selection: Score all candidates by the scoring algorithm (Section 5), pick top 2
|
||||
|
||||
**Cross-sector (multi-sector sites):**
|
||||
- Same logic but across sectors — two clusters from different sectors sharing an attribute value
|
||||
- These are rarer and higher-value because they connect separate topical areas
|
||||
- Example: "Agile PM Tools" (PM sector) and "Sprint Planning CRM" (CRM sector) both have Use Case = Agile
|
||||
- Cross-sector links get a 1.5x score multiplier because they're harder for competitors to replicate
|
||||
- Maximum 1 cross-sector link per hub page (don't dilute primary sector authority)
|
||||
|
||||
**Shared attribute value check (pseudocode):**
|
||||
```
|
||||
for each cluster_a.hub_page:
|
||||
candidates = []
|
||||
for each cluster_b in blueprint.clusters:
|
||||
if cluster_b == cluster_a: skip
|
||||
shared = intersection(cluster_a.attribute_values, cluster_b.attribute_values)
|
||||
if len(shared) >= 1:
|
||||
score = calculate_link_score(cluster_a, cluster_b, shared)
|
||||
candidates.append((cluster_b, score))
|
||||
sort candidates by score desc
|
||||
create_links(top 2 candidates)
|
||||
```
|
||||
|
||||
**Inputs from existing docs:** Blueprint JSON `cross_cluster_links` field already stores these relationships per cluster
|
||||
|
||||
---
|
||||
|
||||
### Section 9: Link Injection Method
|
||||
|
||||
**Content:**
|
||||
Where exactly in the content links get placed.
|
||||
|
||||
**During content generation (New Content Mode):**
|
||||
- AI content generation prompts include link injection instructions
|
||||
- Links are placed BEFORE content enters the review queue (pipeline Stage 7 reference)
|
||||
- Writer module receives link targets from the Linker as part of the task context
|
||||
|
||||
**Link placement zones per page type:**
|
||||
|
||||
**Blog Posts / Supporting Content:**
|
||||
- Zone 1: In-body contextual (primary) — links woven into paragraph text where topically natural
|
||||
- Hub link: Within first 2 paragraphs, at first natural mention of cluster topic
|
||||
- Sibling links: In relevant body sections, natural context
|
||||
- Cross-cluster links: In sections discussing related topics
|
||||
- Zone 2: "Related Reading" section at end of article (2-3 links)
|
||||
- Zone 3: Breadcrumb at top (structural, always present)
|
||||
|
||||
**Cluster Hub Pages:**
|
||||
- Zone 1: In-body contextual — links to supporting content within guide sections
|
||||
- Zone 2: "Articles in This Guide" / "Complete Guide Contents" section — all supporting articles listed
|
||||
- Zone 3: "Related Topics" section — cross-cluster hub links (max 2)
|
||||
- Zone 4: Breadcrumb at top
|
||||
|
||||
**Attribute Term Pages:**
|
||||
- Zone 1: Intro paragraph — link to the primary cluster hub for this term
|
||||
- Zone 2: "Explore by Topic" section — all connected cluster hubs listed with brief descriptions
|
||||
- Zone 3: "Top [Term] Products/Services" — links to relevant products/services
|
||||
- Zone 4: "Related Guides" — links to supporting blogs across clusters
|
||||
|
||||
**Product/Service Pages:**
|
||||
- Zone 1: In description — link to cluster hub this product belongs to
|
||||
- Zone 2: "Specifications" or "Details" section — links to attribute term pages for the product's attribute values
|
||||
- Zone 3: "Related Products" — sibling products in same cluster
|
||||
|
||||
---
|
||||
|
||||
### Section 10: Existing Content Audit Mode
|
||||
|
||||
**Content:**
|
||||
How the Linker scans already-published content and identifies missing SAG links.
|
||||
|
||||
**Trigger:** User clicks "Audit Links" in Linker module, or automatic weekly scan via blueprint health monitoring
|
||||
|
||||
**Audit process:**
|
||||
1. Load active blueprint — get all clusters, page types, expected link relationships
|
||||
2. Crawl all published content (from IGNY8 content records, not live site)
|
||||
3. For each page, extract all outbound links (parse HTML content)
|
||||
4. Compare actual links vs expected links per the rules in Sections 3-8
|
||||
5. Generate gap report
|
||||
|
||||
**Gap report output per page:**
|
||||
- Missing mandatory links (e.g., blog post has no link to its hub)
|
||||
- Missing cross-cluster links (hub has 0 of 2 recommended)
|
||||
- Missing attribute term links
|
||||
- Over-linked pages (exceeding density limits)
|
||||
- Orphan pages (no inbound links from any SAG page)
|
||||
|
||||
**Recommendation generation:**
|
||||
- For each missing link: target URL, suggested anchor text (3 variants), suggested placement zone
|
||||
- For over-linked pages: which links to remove (lowest-scoring by algorithm)
|
||||
- Priority ordering: mandatory gaps first, then high-authority gaps, then nice-to-haves
|
||||
|
||||
**User workflow:** Linker presents recommendations → user approves/rejects per link → approved links auto-injected into content → content republished to WordPress
|
||||
|
||||
---
|
||||
|
||||
### Section 11: New Content Mode
|
||||
|
||||
**Content:**
|
||||
How links are automatically inserted during content generation, before the content enters the review queue.
|
||||
|
||||
**Integration point:** Pipeline Stage 4 (Content Generation) → Linker adds link context to Writer task
|
||||
|
||||
**Flow:**
|
||||
1. Writer task created with `sag_cluster_id` and `blueprint_context`
|
||||
2. Before content generation, Linker calculates required links for this content piece:
|
||||
- What cluster is this? → Mandatory link to cluster hub
|
||||
- What page type is this? → Apply density rules
|
||||
- What sibling content exists in this cluster? → Sibling link candidates
|
||||
- What cross-cluster opportunities exist? → Cross-cluster candidates
|
||||
3. Link targets + anchor text suggestions passed to AI content generation prompt
|
||||
4. AI generates content WITH links embedded
|
||||
5. Post-generation link validation: verify all mandatory links present, density within limits
|
||||
6. Content enters review queue with links pre-inserted
|
||||
|
||||
**Prompt enhancement (added to Thinker prompts):**
|
||||
```
|
||||
Link requirements for this content:
|
||||
- MANDATORY: Link to [hub_url] with anchor text "[primary_keyword]" within first 2 paragraphs
|
||||
- RECOMMENDED: Link to [sibling_url_1] with anchor "[suggested_anchor]" where contextually relevant
|
||||
- RECOMMENDED: Link to [cross_cluster_url] with anchor "[suggested_anchor]" if topic comes up naturally
|
||||
- Total outbound links: [min]-[max] based on content length
|
||||
- Do NOT use "click here" or "read more" as anchor text
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Section 12: Link Health Monitoring
|
||||
|
||||
**Content:**
|
||||
Ongoing monitoring that feeds into the SAG Health Score.
|
||||
|
||||
**Checks (run weekly or on-demand):**
|
||||
- Broken links: Published URLs that return 404 or redirect chains
|
||||
- Orphan pages: Pages with 0 inbound SAG links (every page should have at least 1)
|
||||
- Authority flow gaps: Clusters where hub has backlinks but supporting content has <2 inbound links
|
||||
- Over-linked pages: Pages exceeding density maximums
|
||||
- Missing mandatory links: Any supporting blog without a hub link
|
||||
- Stale cross-links: Cross-cluster links pointing to hubs whose clusters have been restructured
|
||||
- Anchor text over-optimization: Same exact anchor pointing to same URL more than 3 times site-wide
|
||||
|
||||
**Health score contribution:**
|
||||
The link coverage score (0-100) on SAGCluster model is calculated as:
|
||||
- Hub page published and has all mandatory links? (25 points)
|
||||
- All supporting content links back to hub? (25 points)
|
||||
- At least 1 cross-cluster link on hub? (15 points)
|
||||
- All attribute term pages link to this hub? (15 points)
|
||||
- No broken links within cluster? (10 points)
|
||||
- Density within limits for all cluster pages? (10 points)
|
||||
|
||||
**Alert thresholds:**
|
||||
- Cluster link score < 50: Flag as "needs attention" in dashboard
|
||||
- Orphan page detected: Immediate alert
|
||||
- Broken link detected: Add to fix queue
|
||||
- 3+ same exact anchor text: Over-optimization warning
|
||||
|
||||
---
|
||||
|
||||
### Section 13: Reporting & Visualization
|
||||
|
||||
**Content:**
|
||||
What the Linker module shows in the IGNY8 UI.
|
||||
|
||||
**Cluster-Level Link Coverage Report:**
|
||||
- Table showing all clusters with: cluster name, hub status (published/draft/missing), supporting content count, link coverage score, missing links count
|
||||
- Color coding: green (score 80+), yellow (50-79), red (<50)
|
||||
- Click into cluster → see all pages, all links, all gaps
|
||||
|
||||
**Site-Wide Link Map:**
|
||||
- Visual showing clusters as nodes, with lines connecting cross-linked hubs
|
||||
- Attribute term pages as connecting nodes between clusters
|
||||
- Thickness of lines = number of links between nodes
|
||||
- Helps users see which parts of the grid are well-connected vs isolated
|
||||
|
||||
**Link Audit Dashboard:**
|
||||
- Total links site-wide
|
||||
- Missing mandatory links count
|
||||
- Orphan pages count
|
||||
- Over-linked pages count
|
||||
- Top 10 most-linked pages (should be hubs)
|
||||
- Top 10 least-linked pages (should be investigated)
|
||||
- Average links per page by type
|
||||
|
||||
**Gap Analysis Export:**
|
||||
- Downloadable report of all missing links with recommendations
|
||||
- Format matching existing IGNY8 export patterns
|
||||
|
||||
---
|
||||
|
||||
### Section 14: Data Models
|
||||
|
||||
**Content:**
|
||||
New models and fields needed for the Linker module.
|
||||
|
||||
**SAGLink (new model)**
|
||||
```
|
||||
- id (UUID)
|
||||
- blueprint_id (FK → SAGBlueprint)
|
||||
- source_content_id (FK → Content)
|
||||
- target_content_id (FK → Content, nullable — for external/term page targets)
|
||||
- target_url (String — for term pages or external)
|
||||
- link_type (Enum: hub_upward, hub_downward, sibling, cross_cluster, taxonomy_contextual, breadcrumb, related_content)
|
||||
- anchor_text (String)
|
||||
- placement_zone (Enum: in_body, related_section, breadcrumb, specification, guide_contents)
|
||||
- status (Enum: planned, injected, published, broken, removed)
|
||||
- score (Float — from scoring algorithm)
|
||||
- created_at, injected_at
|
||||
```
|
||||
|
||||
**SAGLinkAudit (new model)**
|
||||
```
|
||||
- id (UUID)
|
||||
- blueprint_id (FK → SAGBlueprint)
|
||||
- audit_date (DateTime)
|
||||
- total_links (Integer)
|
||||
- missing_mandatory (Integer)
|
||||
- orphan_pages (Integer)
|
||||
- broken_links (Integer)
|
||||
- over_linked_pages (Integer)
|
||||
- cluster_scores (JSON — {cluster_id: score} map)
|
||||
- recommendations (JSON — array of link recommendations)
|
||||
```
|
||||
|
||||
**Modified existing models:**
|
||||
- SAGCluster: `link_coverage_score` already defined — this doc defines how it's calculated (Section 12)
|
||||
- Content: Add `outbound_link_count` (Integer), `inbound_link_count` (Integer) — cached counters
|
||||
|
||||
---
|
||||
|
||||
### Section 15: Integration with IGNY8 Pipeline
|
||||
|
||||
**Content:**
|
||||
How the Linker module fits into the existing IGNY8 workflow and automation.
|
||||
|
||||
**Manual mode:**
|
||||
- User publishes content → clicks "Generate Links" in Linker → reviews recommendations → approves → links injected
|
||||
- User runs "Audit Links" → sees gap report → approves fixes → links updated
|
||||
|
||||
**Automation mode (pipeline extension):**
|
||||
- After Stage 7 (images generated), new Stage 8: Link Generation
|
||||
- Load blueprint, get cluster context for this content
|
||||
- Generate required links per rules
|
||||
- Inject into content HTML
|
||||
- Content enters review queue with links already present
|
||||
- After publish → async link audit checks all pages in cluster for completeness
|
||||
|
||||
**WordPress plugin integration:**
|
||||
- When content publishes to WordPress, links are already in the HTML
|
||||
- Plugin does NOT need to do link processing — IGNY8 app handles all link logic
|
||||
- Plugin reports back published URL → IGNY8 updates SAGLink records with final published URLs
|
||||
|
||||
---
|
||||
|
||||
### Section 16: MassagerSmart Reference Example
|
||||
|
||||
**Content:**
|
||||
Walk through the complete interlinking architecture for MassagerSmart.com as the reference implementation.
|
||||
|
||||
**Example cluster: "Foot Massagers for Neuropathy"**
|
||||
- Hub page: "Best Foot Massagers for Neuropathy & Nerve Pain Relief"
|
||||
- Links DOWN to: "Doctor-Recommended Foot Massagers for Neuropathy", "EMS vs TENS for Neuropathy", "Does a Foot Massager Actually Help Neuropathy?"
|
||||
- Links ACROSS to: "EMS Foot Massagers" hub (shared value: Foot), "Heated Foot Massagers" hub (shared value: Foot)
|
||||
- Links UP to: Sector landing page
|
||||
- Supporting blog: "Doctor-Recommended Foot Massagers for Neuropathy"
|
||||
- Links UP to: Hub page (mandatory)
|
||||
- Links to SIBLING: "EMS vs TENS for Neuropathy" (shared cluster)
|
||||
- Links to RELATED: "Shiatsu Foot Massagers" hub (different cluster, related topic)
|
||||
- Attribute Term Page: "Neuropathy"
|
||||
- Links to: "Foot Massagers for Neuropathy" hub, "EMS Massagers for Neuropathy" hub, "Heated Massagers for Neuropathy" hub — all hubs where Relief Focus = Neuropathy
|
||||
|
||||
Show the complete link map for 3-4 clusters demonstrating all 7 link types in practice.
|
||||
|
||||
---
|
||||
|
||||
### Section 17: Cross-References
|
||||
|
||||
**Content:**
|
||||
- SAG Master Document — Pure methodology reference
|
||||
- SAG Implementation for IGNY8 — Three-layer architecture, blueprint JSON, data models, pipeline integration (primary dependency)
|
||||
- SAG Niche Definition Process — Cluster formation rules that determine link structure (Document 2)
|
||||
- SAG Backlink Campaign Specification — External links that feed the internal authority flow (Document 4)
|
||||
|
||||
---
|
||||
|
||||
## Build Plan
|
||||
|
||||
This document will be built as Markdown (.md) for the IGNY8 repo, matching the format of SAG-IGNY8-Implementation.md. Estimated 800-1,000 lines across 17 sections. Can be built section by section in one session, or split into 2 sessions if needed.
|
||||
|
||||
Sections 1-4 establish the conceptual framework (page types, link types, authority flow).
|
||||
Sections 5-8 define the rules engine (scoring, anchors, density, cross-cluster).
|
||||
Sections 9-11 define the two operating modes (audit existing, generate for new).
|
||||
Sections 12-13 define monitoring and reporting.
|
||||
Sections 14-15 define data models and pipeline integration.
|
||||
Section 16 is the worked example.
|
||||
Section 17 is cross-references.
|
||||
1278
v2/Igny8 V2 New Final Plans/SAG-IGNY8-Implementation.md
Normal file
1278
v2/Igny8 V2 New Final Plans/SAG-IGNY8-Implementation.md
Normal file
File diff suppressed because it is too large
Load Diff
1048
v2/Igny8 V2 New Final Plans/SAG-Master-Document.md
Normal file
1048
v2/Igny8 V2 New Final Plans/SAG-Master-Document.md
Normal file
File diff suppressed because it is too large
Load Diff
BIN
v2/Igny8 V2 New Final Plans/SAG-Niche-Definition-Process.pdf
Normal file
BIN
v2/Igny8 V2 New Final Plans/SAG-Niche-Definition-Process.pdf
Normal file
Binary file not shown.
1054
v2/Igny8 V2 New Final Plans/Theme-Build-Plan.md
Normal file
1054
v2/Igny8 V2 New Final Plans/Theme-Build-Plan.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user