diff --git a/website/DEPLOYMENT.md b/website/DEPLOYMENT.md
new file mode 100644
index 00000000..3c6ae39c
--- /dev/null
+++ b/website/DEPLOYMENT.md
@@ -0,0 +1,227 @@
+# AITBC Agent-First Website Deployment
+
+This directory contains an **agent-first website** that provides machine-readable discovery endpoints for autonomous agents.
+
+## Quick Start
+
+### 1. Serve Directly from Repository
+
+The website is designed to be served directly from this repository location:
+
+```bash
+# Using Python (development)
+cd /opt/aitbc/website
+python3 -m http.server 8080
+
+# Using nginx (production) - see nginx-example.conf
+sudo cp nginx-example.conf /etc/nginx/sites-available/aitbc-agent
+sudo ln -s /etc/nginx/sites-available/aitbc-agent /etc/nginx/sites-enabled/
+sudo nginx -t
+sudo systemctl reload nginx
+```
+
+### 2. Configure Node-Specific Settings
+
+Edit the JSON files to match your node's role:
+
+**For aitbc (Mainnet Hub):**
+- `agent/discovery.json` - Already configured for mainnet
+- `agent/islands.json` - Shows ait-mainnet-island only
+- `agent/chains.json` - Shows ait-mainnet only
+- Remove `agent/join/ait-testnet.json` if present
+
+**For aitbc1 (Testnet Hub):**
+- `agent/discovery.json` - Update to testnet configuration
+- `agent/islands.json` - Update to show ait-testnet-island
+- `agent/chains.json` - Update to show ait-testnet
+- Remove `agent/join/ait-mainnet.json`
+
+### 3. Enable Live API (Optional but Recommended)
+
+The live API provides real-time data from the blockchain RPC:
+
+```bash
+# Install systemd service
+sudo cp systemd-example.service /etc/systemd/system/aitbc-agent-live-api.service
+
+# Edit to match your node configuration
+sudo systemctl edit aitbc-agent-live-api.service
+
+# Enable and start
+sudo systemctl daemon-reload
+sudo systemctl enable aitbc-agent-live-api
+sudo systemctl start aitbc-agent-live-api
+```
+
+## Directory Structure
+
+```
+website/
+├── index.html # Agent landing page (human-readable)
+├── DEPLOYMENT.md # This file
+├── nginx-example.conf # Example nginx configuration
+├── systemd-example.service # Example systemd service
+├── agent/ # Machine-readable endpoints
+│ ├── index.html # Agent API documentation
+│ ├── discovery.json # Network discovery (static)
+│ ├── islands.json # Island config (static)
+│ ├── chains.json # Chain config (static)
+│ ├── openapi.json # API specification
+│ ├── live_api.py # Live API service (dynamic)
+│ ├── health # Health check
+│ └── join/ # Join instructions
+│ ├── ait-mainnet.json
+│ └── ait-testnet.json
+└── assets/ # Static assets (minimal)
+```
+
+## Endpoints
+
+### Static Endpoints (Fast, Cached)
+
+| Endpoint | Description | Cache |
+|----------|-------------|-------|
+| `/agent/discovery.json` | Network topology | 60s |
+| `/agent/islands.json` | Island configuration | 30s |
+| `/agent/chains.json` | Chain configuration | 60s |
+| `/agent/join/*.json` | Join instructions | 1h |
+
+### Live Endpoints (Real-Time, Requires live_api.py)
+
+| Endpoint | Description | Cache |
+|----------|-------------|-------|
+| `/agent/live/discovery.json` | Real-time discovery | No cache |
+| `/agent/live/islands.json` | Live island data | No cache |
+| `/agent/live/chains.json` | Live chain data | No cache |
+| `/agent/live/health` | Real-time health | No cache |
+
+### RPC Endpoints (Blockchain Access)
+
+| Endpoint | Description |
+|----------|-------------|
+| `/rpc/head` | Current block height |
+| `/rpc/info` | Chain information |
+| `/rpc/islands` | Island memberships |
+
+## Node Configuration
+
+### Mainnet Hub (aitbc)
+
+```json
+// agent/discovery.json
+"this_node": {
+ "node_id": "aitbc",
+ "role": "hub",
+ "chains": ["ait-mainnet"],
+ "island_memberships": ["ait-mainnet-island"]
+}
+```
+
+### Testnet Hub (aitbc1)
+
+```json
+// agent/discovery.json
+"this_node": {
+ "node_id": "aitbc1",
+ "role": "hub",
+ "chains": ["ait-testnet"],
+ "island_memberships": ["ait-testnet-island"]
+}
+```
+
+## Testing
+
+```bash
+# Test static endpoint
+curl -s http://localhost/agent/discovery.json | jq .
+
+# Test live endpoint (if live_api.py is running)
+curl -s http://localhost/agent/live/islands.json | jq .
+
+# Test RPC endpoint
+curl -s http://localhost/rpc/head | jq .
+
+# Check CORS headers
+curl -I http://localhost/agent/discovery.json
+```
+
+## Security Notes
+
+1. **CORS**: All `/agent/` and `/rpc/` endpoints have `Access-Control-Allow-Origin: *` for agent access
+2. **Static files**: No sensitive data in JSON files (only public network info)
+3. **Live API**: Runs on localhost only (127.0.0.1:8080), proxied by nginx
+4. **No auth**: Discovery endpoints are public by design
+
+## Troubleshooting
+
+**Live API not responding:**
+```bash
+# Check service status
+sudo systemctl status aitbc-agent-live-api
+
+# Check logs
+sudo journalctl -u aitbc-agent-live-api -f
+
+# Test directly
+curl http://127.0.0.1:8080/agent/live/health
+```
+
+**Nginx config errors:**
+```bash
+# Test configuration
+sudo nginx -t
+
+# Check error logs
+sudo tail -f /var/log/nginx/error.log
+```
+
+**JSON files not updating:**
+- Static files are cached - edit directly in `/opt/aitbc/website/agent/`
+- For live data, ensure `live_api.py` is running
+- Check file permissions: `sudo chown -R www-data:www-data /opt/aitbc/website/`
+
+## Git Workflow
+
+Since the website is served directly from the repo:
+
+```bash
+# Edit files
+cd /opt/aitbc/website
+vim agent/discovery.json
+
+# Test locally
+python3 -m http.server 8080
+
+# Commit changes
+git add .
+git commit -m "Update discovery for mainnet hub"
+git push
+
+# Changes are live immediately (no deploy needed)
+```
+
+## Architecture
+
+```
+┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
+│ Autonomous │────▶│ Nginx (80/443) │────▶│ Static JSON │
+│ Agent │ │ │ │ (discovery) │
+└─────────────────┘ │ ┌───────────┐ │ └─────────────────┘
+ │ │ /agent/* │ │
+ │ │ /rpc/* │ │ ┌─────────────────┐
+ │ └─────┬─────┘ │────▶│ Live API │
+ │ │ │ │ (port 8080) │
+ │ └────┬────┘ └─────┬───────────┘
+ │ │ │
+ └─────────────┘ │
+ ▼
+ ┌─────────────────┐
+ │ Blockchain RPC │
+ │ (port 8006) │
+ └─────────────────┘
+```
+
+## Support
+
+- Repository: https://github.com/oib/AITBC
+- Documentation: `/agent/index.html` (served at `http://your-node/agent/`)
diff --git a/website/agent/chains.json b/website/agent/chains.json
deleted file mode 100644
index 715ff664..00000000
--- a/website/agent/chains.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "chains": [
- {
- "chain_id": "ait-mainnet",
- "name": "AIT Mainnet",
- "island_id": "ait-mainnet-island",
- "type": "production",
- "status": "active",
- "config": {
- "block_time": 5,
- "consensus": "proof_of_authority",
- "network_id": 1337,
- "enable_empty_blocks": true,
- "max_empty_block_interval": 60
- },
- "endpoints": {
- "rpc": ["http://aitbc:8006/rpc", "http://aitbc1:8006/rpc"],
- "head": "/rpc/head",
- "info": "/rpc/info",
- "supply": "/rpc/supply"
- },
- "join": {
- "p2p": {
- "port": 7070,
- "peers": ["aitbc:7070", "aitbc1:7070"]
- },
- "sync": {
- "source": "http://aitbc1:8006",
- "chain_id": "ait-mainnet"
- },
- "guide": "/agent/join/ait-mainnet.json"
- }
- }
- ],
- "_meta": {
- "generated_at": "2026-05-19T15:50:00Z",
- "format_version": "1.0",
- "total_chains": 1,
- "active_chains": 1,
- "note": "This endpoint only shows chains where this node (aitbc) is the HUB"
- }
-}
diff --git a/website/agent/discovery.json b/website/agent/discovery.json
deleted file mode 100644
index e6d24971..00000000
--- a/website/agent/discovery.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{
- "network": {
- "name": "AITBC",
- "version": "1.0.0",
- "description": "AI-powered blockchain platform with multi-island architecture",
- "apis": {
- "rpc": {
- "url": "http://localhost:8006/rpc",
- "documentation": "/agent/openapi.json",
- "version": "1.0"
- },
- "agent": {
- "discovery": "/agent/discovery.json",
- "islands": "/agent/islands.json",
- "chains": "/agent/chains.json",
- "health": "/agent/health",
- "join": "/agent/join/"
- }
- },
- "islands": [
- {
- "island_id": "ait-mainnet-island",
- "name": "AIT Mainnet",
- "chain_id": "ait-mainnet",
- "status": "active",
- "description": "Primary production chain for AITBC",
- "endpoints": {
- "rpc": ["http://aitbc:8006", "http://aitbc1:8006"],
- "p2p": ["aitbc:7070", "aitbc1:7070"]
- },
- "chain_info": {
- "block_time": 5,
- "consensus": "proof_of_authority",
- "network_id": 1337
- },
- "join_guide": "/agent/join/ait-mainnet.json",
- "note": "This node (aitbc) is the HUB for this island"
- }
- ]
- },
- "this_node": {
- "node_id": "aitbc",
- "role": "hub",
- "is_hub": true,
- "block_production": true,
- "chains": ["ait-mainnet"],
- "island_memberships": ["ait-mainnet-island"],
- "discovery_url": "http://aitbc:8006/agent/discovery.json"
- },
- "_meta": {
- "generated_at": "2026-05-19T15:50:00Z",
- "format_version": "1.0"
- }
-}
diff --git a/website/agent/index.html b/website/agent/index.html
index d643d838..e1eb9adc 100644
--- a/website/agent/index.html
+++ b/website/agent/index.html
@@ -165,7 +165,7 @@
-
Agent-First Design: This page provides human-readable documentation, but all endpoints return structured JSON for programmatic consumption. Start with
/agent/discovery.json for complete network information.
+
Live Data Only: All API endpoints return real-time data from the blockchain RPC. No static files - everything is queried live from the node.
@@ -176,12 +176,7 @@
active
Island: ait-mainnet-island
Role: Hub (Block Production)
-
-
-
AIT Testnet
-
active
-
Island: ait-testnet-island
-
Role: Follower (Syncing)
+
Live data from RPC
diff --git a/website/agent/islands.json b/website/agent/islands.json
deleted file mode 100644
index 2ba59ed4..00000000
--- a/website/agent/islands.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- "islands": [
- {
- "island_id": "ait-mainnet-island",
- "island_name": "AIT Mainnet",
- "chain_id": "ait-mainnet",
- "status": "active",
- "role": "hub",
- "chain_info": {
- "block_time": 5,
- "consensus": "proof_of_authority",
- "network_id": 1337,
- "genesis_timestamp": "2026-05-19T14:44:44.174290"
- },
- "endpoints": {
- "rpc": [
- {
- "url": "http://aitbc:8006",
- "node_id": "aitbc",
- "role": "hub"
- },
- {
- "url": "http://aitbc1:8006",
- "node_id": "aitbc1",
- "role": "follower"
- }
- ],
- "p2p": [
- {
- "address": "aitbc:7070",
- "node_id": "aitbc"
- },
- {
- "address": "aitbc1:7070",
- "node_id": "aitbc1"
- }
- ]
- },
- "this_node": {
- "node_id": "aitbc",
- "role": "hub",
- "is_hub": true,
- "block_production_chains": ["ait-mainnet"],
- "enable_block_production": true
- }
- }
- ],
- "_meta": {
- "generated_at": "2026-05-19T15:50:00Z",
- "format_version": "1.0",
- "total_islands": 1,
- "active_islands": 1,
- "note": "This endpoint only shows islands where this node (aitbc) is the HUB"
- }
-}
diff --git a/website/agent/join/ait-mainnet.json b/website/agent/join/ait-mainnet.json
deleted file mode 100644
index 65c3b311..00000000
--- a/website/agent/join/ait-mainnet.json
+++ /dev/null
@@ -1,121 +0,0 @@
-{
- "chain_id": "ait-mainnet",
- "island_id": "ait-mainnet-island",
- "name": "AIT Mainnet",
- "description": "Primary production chain for AITBC platform",
- "type": "production",
- "status": "active",
- "requirements": {
- "minimum_version": "1.0.0",
- "required_services": ["aitbc-blockchain-node", "aitbc-blockchain-rpc"],
- "ports": {
- "p2p": 7070,
- "rpc": 8006
- }
- },
- "how_to_join": {
- "step_1_environment": {
- "description": "Configure node.env for this node",
- "file": "/etc/aitbc/node.env",
- "variables": {
- "NODE_ID": "your-node-id",
- "p2p_node_id": "node-$(uuidgen | tr -d '-')",
- "p2p_bind_host": "0.0.0.0",
- "p2p_bind_port": "7070",
- "proposer_id": "your-proposer-id",
- "p2p_peers": "aitbc:7070,aitbc1:7070",
- "enable_block_production": "false",
- "block_production_chains": ""
- },
- "note": "Set enable_block_production=false for follower nodes"
- },
- "step_2_blockchain_env": {
- "description": "Configure blockchain.env",
- "file": "/etc/aitbc/blockchain.env",
- "variables": {
- "island_id": "ait-mainnet-island",
- "supported_chains": "ait-mainnet",
- "CHAIN_ID": "ait-mainnet",
- "auto_sync_enabled": "true",
- "default_peer_rpc_url": "http://aitbc1:8006",
- "SYNC_SOURCE_HOST": "aitbc1",
- "SYNC_SOURCE_PORT": "8006",
- "SYNC_CHAIN_ID": "ait-mainnet"
- }
- },
- "step_3_networking": {
- "description": "Ensure network connectivity",
- "requirements": [
- "Port 7070 open for P2P communication",
- "Port 8006 open for RPC access",
- "Connectivity to aitbc (10.1.223.93) and aitbc1 (10.1.223.40)"
- ]
- },
- "step_4_start_services": {
- "description": "Start blockchain services",
- "commands": [
- "systemctl start aitbc-blockchain-node.service",
- "systemctl start aitbc-blockchain-rpc.service"
- ]
- },
- "step_5_verify": {
- "description": "Verify successful join",
- "commands": [
- "curl -s http://localhost:8006/rpc/head",
- "sqlite3 /var/lib/aitbc/data/ait-mainnet/chain.db 'SELECT MAX(height) FROM block'"
- ],
- "expected_result": "Block height should be increasing as blocks are synced"
- }
- },
- "endpoints": {
- "rpc": {
- "hub": "http://aitbc:8006",
- "backup": "http://aitbc1:8006"
- },
- "p2p": {
- "peers": ["aitbc:7070", "aitbc1:7070"]
- }
- },
- "configuration_templates": {
- "follower_node": {
- "node.env": {
- "NODE_ID": "your-node-id",
- "p2p_node_id": "node-unique-uuid",
- "p2p_bind_host": "0.0.0.0",
- "p2p_bind_port": "7070",
- "proposer_id": "ait1your-proposer-id",
- "p2p_peers": "aitbc:7070,aitbc1:7070",
- "trusted_proposers": "",
- "block_production_chains": "",
- "enable_block_production": "false"
- },
- "blockchain.env": {
- "auto_sync_enabled": "true",
- "island_id": "ait-mainnet-island",
- "supported_chains": "ait-mainnet",
- "default_peer_rpc_url": "http://aitbc1:8006",
- "SYNC_SOURCE_HOST": "aitbc1",
- "SYNC_SOURCE_PORT": "8006",
- "SYNC_CHAIN_ID": "ait-mainnet"
- }
- }
- },
- "troubleshooting": {
- "gap_detected_errors": {
- "cause": "Node is receiving blocks but missing intermediate blocks",
- "solution": "Ensure auto_sync_enabled=true and default_peer_rpc_url points to active hub"
- },
- "fork_detection": {
- "cause": "Multiple nodes with same proposer_id producing blocks",
- "solution": "Ensure enable_block_production=false on follower nodes"
- },
- "p2p_connection_failed": {
- "cause": "Cannot connect to P2P peers",
- "solution": "Verify p2p_bind_host and p2p_bind_port are set correctly, check firewall rules"
- }
- },
- "_meta": {
- "format_version": "1.0",
- "updated_at": "2026-05-19T15:50:00Z"
- }
-}
diff --git a/website/agent/live_api.py b/website/agent/live_api.py
new file mode 100644
index 00000000..60be7e82
--- /dev/null
+++ b/website/agent/live_api.py
@@ -0,0 +1,317 @@
+#!/usr/bin/env python3
+"""
+AITBC Agent Live API
+Real-time dynamic endpoints that query blockchain RPC and serve fresh data
+"""
+
+import json
+import os
+import sys
+from datetime import datetime, timezone
+from pathlib import Path
+from typing import Dict, Any, Optional
+
+# Try to import fastapi, fallback to flask
+try:
+ from fastapi import FastAPI, HTTPException
+ from fastapi.responses import JSONResponse
+ import uvicorn
+ HAS_FASTAPI = True
+except ImportError:
+ try:
+ from flask import Flask, jsonify, abort
+ HAS_FLASK = True
+ except ImportError:
+ print("Error: Neither FastAPI nor Flask installed")
+ sys.exit(1)
+
+import urllib.request
+import urllib.error
+import ssl
+
+# Configuration
+RPC_URL = os.getenv("AITBC_RPC_URL", "http://localhost:8006/rpc")
+NODE_ID = os.getenv("NODE_ID", "aitbc")
+ISLAND_ID = os.getenv("ISLAND_ID", "ait-mainnet-island")
+CHAIN_ID = os.getenv("CHAIN_ID", "ait-mainnet")
+NODE_ROLE = os.getenv("NODE_ROLE", "hub")
+
+# SSL context that doesn't verify certs (for local dev)
+ssl_context = ssl.create_default_context()
+ssl_context.check_hostname = False
+ssl_context.verify_mode = ssl.CERT_NONE
+
+
+def rpc_query(method: str, params: Optional[list] = None) -> Optional[Dict]:
+ """Query the blockchain RPC endpoint"""
+ try:
+ url = f"{RPC_URL}/{method}"
+ req = urllib.request.Request(
+ url,
+ headers={
+ "Accept": "application/json",
+ "Content-Type": "application/json"
+ }
+ )
+ with urllib.request.urlopen(req, timeout=5, context=ssl_context) as response:
+ return json.loads(response.read().decode())
+ except Exception as e:
+ print(f"RPC query failed: {e}", file=sys.stderr)
+ return None
+
+
+def get_live_island_data() -> Dict[str, Any]:
+ """Get real-time island data from RPC"""
+ # Query chain head for current block info
+ head = rpc_query("head")
+ info = rpc_query("info")
+ islands_rpc = rpc_query("islands")
+
+ # Get peer count from island manager if available
+ peer_count = 0
+ if islands_rpc and isinstance(islands_rpc, dict) and "islands" in islands_rpc:
+ for island in islands_rpc["islands"]:
+ if island.get("island_id") == ISLAND_ID:
+ peer_count = island.get("peer_count", 0)
+ break
+
+ block_height = head.get("height", 0) if head else 0
+ block_hash = head.get("hash", "unknown") if head else "unknown"
+ timestamp = head.get("timestamp", datetime.now(timezone.utc).isoformat()) if head else datetime.now(timezone.utc).isoformat()
+
+ return {
+ "islands": [
+ {
+ "island_id": ISLAND_ID,
+ "island_name": "AIT Mainnet" if CHAIN_ID == "ait-mainnet" else "AIT Testnet",
+ "chain_id": CHAIN_ID,
+ "status": "active",
+ "role": NODE_ROLE,
+ "chain_info": {
+ "block_time": 5,
+ "consensus": "proof_of_authority",
+ "network_id": 1337,
+ "current_height": block_height,
+ "current_hash": block_hash,
+ "last_update": timestamp
+ },
+ "endpoints": {
+ "rpc": [
+ {"url": f"http://{NODE_ID}:8006", "node_id": NODE_ID, "role": NODE_ROLE},
+ {"url": f"http://{'aitbc1' if NODE_ID == 'aitbc' else 'aitbc'}:8006",
+ "node_id": 'aitbc1' if NODE_ID == 'aitbc' else 'aitbc',
+ "role": "follower" if NODE_ROLE == "hub" else "hub"}
+ ],
+ "p2p": [
+ {"address": f"{NODE_ID}:7070", "node_id": NODE_ID},
+ {"address": f"{'aitbc1' if NODE_ID == 'aitbc' else 'aitbc'}:7070",
+ "node_id": 'aitbc1' if NODE_ID == 'aitbc' else 'aitbc'}
+ ]
+ },
+ "stats": {
+ "peer_count": peer_count,
+ "block_height": block_height,
+ "last_block_hash": block_hash,
+ "last_block_time": timestamp
+ },
+ "this_node": {
+ "node_id": NODE_ID,
+ "role": NODE_ROLE,
+ "is_hub": NODE_ROLE == "hub",
+ "block_production_chains": [CHAIN_ID] if NODE_ROLE == "hub" else [],
+ "enable_block_production": NODE_ROLE == "hub"
+ }
+ }
+ ],
+ "_meta": {
+ "generated_at": datetime.now(timezone.utc).isoformat(),
+ "format_version": "1.0",
+ "total_islands": 1,
+ "active_islands": 1,
+ "data_source": "live_rpc",
+ "note": "This endpoint shows real-time data from the blockchain RPC"
+ }
+ }
+
+
+def get_live_chain_data() -> Dict[str, Any]:
+ """Get real-time chain data from RPC"""
+ head = rpc_query("head")
+ info = rpc_query("info")
+
+ block_height = head.get("height", 0) if head else 0
+ block_hash = head.get("hash", "unknown") if head else "unknown"
+ timestamp = head.get("timestamp", datetime.now(timezone.utc).isoformat()) if head else datetime.now(timezone.utc).isoformat()
+ tx_count = head.get("tx_count", 0) if head else 0
+
+ return {
+ "chains": [
+ {
+ "chain_id": CHAIN_ID,
+ "name": "AIT Mainnet" if CHAIN_ID == "ait-mainnet" else "AIT Testnet",
+ "island_id": ISLAND_ID,
+ "type": "production" if CHAIN_ID == "ait-mainnet" else "test",
+ "status": "active",
+ "live_stats": {
+ "current_height": block_height,
+ "current_hash": block_hash,
+ "last_block_time": timestamp,
+ "tx_count_last_block": tx_count,
+ "queried_at": datetime.now(timezone.utc).isoformat()
+ },
+ "config": {
+ "block_time": info.get("block_time", 5) if info else 5,
+ "consensus": "proof_of_authority",
+ "network_id": info.get("network_id", 1337) if info else 1337
+ },
+ "endpoints": {
+ "rpc": [
+ f"http://{NODE_ID}:8006/rpc",
+ f"http://{'aitbc1' if NODE_ID == 'aitbc' else 'aitbc'}:8006/rpc"
+ ],
+ "head": "/rpc/head",
+ "info": "/rpc/info",
+ "supply": "/rpc/supply"
+ },
+ "join": {
+ "guide": f"/agent/join/{CHAIN_ID}.json"
+ }
+ }
+ ],
+ "_meta": {
+ "generated_at": datetime.now(timezone.utc).isoformat(),
+ "format_version": "1.0",
+ "total_chains": 1,
+ "active_chains": 1,
+ "data_source": "live_rpc"
+ }
+ }
+
+
+def get_live_discovery() -> Dict[str, Any]:
+ """Get live discovery data"""
+ head = rpc_query("head")
+ health = rpc_query("health") or {}
+
+ block_height = head.get("height", 0) if head else 0
+
+ return {
+ "network": {
+ "name": "AITBC",
+ "version": "1.0.0",
+ "description": "AI-powered blockchain platform",
+ "live_status": {
+ "current_height": block_height,
+ "node_health": health.get("status", "unknown"),
+ "last_update": datetime.now(timezone.utc).isoformat()
+ },
+ "apis": {
+ "rpc": {
+ "url": f"http://{NODE_ID}:8006/rpc",
+ "documentation": "/agent/openapi.json"
+ },
+ "agent": {
+ "discovery": "/agent/discovery.json",
+ "islands": "/agent/islands.json",
+ "chains": "/agent/chains.json",
+ "health": "/agent/health"
+ }
+ },
+ "islands": [
+ {
+ "island_id": ISLAND_ID,
+ "name": "AIT Mainnet" if CHAIN_ID == "ait-mainnet" else "AIT Testnet",
+ "chain_id": CHAIN_ID,
+ "current_height": block_height,
+ "status": "active",
+ "join_guide": f"/agent/join/{CHAIN_ID}.json",
+ "note": f"This node ({NODE_ID}) is the HUB for this island"
+ }
+ ]
+ },
+ "this_node": {
+ "node_id": NODE_ID,
+ "role": NODE_ROLE,
+ "is_hub": NODE_ROLE == "hub",
+ "block_production": NODE_ROLE == "hub",
+ "chains": [CHAIN_ID] if NODE_ROLE == "hub" else [],
+ "island_memberships": [ISLAND_ID],
+ "live_data": True
+ },
+ "_meta": {
+ "generated_at": datetime.now(timezone.utc).isoformat(),
+ "format_version": "1.1",
+ "data_source": "live_rpc"
+ }
+ }
+
+
+# Create app based on available framework
+if HAS_FASTAPI:
+ app = FastAPI(title="AITBC Agent Live API")
+
+ @app.get("/agent/islands.json")
+ async def live_islands():
+ return JSONResponse(content=get_live_island_data())
+
+ @app.get("/agent/chains.json")
+ async def live_chains():
+ return JSONResponse(content=get_live_chain_data())
+
+ @app.get("/agent/discovery.json")
+ async def live_discovery():
+ return JSONResponse(content=get_live_discovery())
+
+ @app.get("/agent/health")
+ async def live_health():
+ head = rpc_query("head")
+ return JSONResponse(content={
+ "status": "healthy" if head else "unhealthy",
+ "node_id": NODE_ID,
+ "chain_id": CHAIN_ID,
+ "current_height": head.get("height", 0) if head else 0,
+ "timestamp": datetime.now(timezone.utc).isoformat()
+ })
+
+elif HAS_FLASK:
+ app = Flask(__name__)
+
+ @app.route("/agent/islands.json")
+ def live_islands():
+ return jsonify(get_live_island_data())
+
+ @app.route("/agent/chains.json")
+ def live_chains():
+ return jsonify(get_live_chain_data())
+
+ @app.route("/agent/discovery.json")
+ def live_discovery():
+ return jsonify(get_live_discovery())
+
+ @app.route("/agent/health")
+ def live_health():
+ head = rpc_query("head")
+ return jsonify({
+ "status": "healthy" if head else "unhealthy",
+ "node_id": NODE_ID,
+ "chain_id": CHAIN_ID,
+ "current_height": head.get("height", 0) if head else 0,
+ "timestamp": datetime.now(timezone.utc).isoformat()
+ })
+
+
+if __name__ == "__main__":
+ import argparse
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--port", type=int, default=8080)
+ parser.add_argument("--host", default="127.0.0.1")
+ args = parser.parse_args()
+
+ print(f"Starting AITBC Agent Live API on {args.host}:{args.port}")
+ print(f"RPC URL: {RPC_URL}")
+ print(f"Node: {NODE_ID} | Chain: {CHAIN_ID} | Role: {NODE_ROLE}")
+
+ if HAS_FASTAPI:
+ uvicorn.run(app, host=args.host, port=args.port)
+ elif HAS_FLASK:
+ app.run(host=args.host, port=args.port)
diff --git a/website/nginx-example.conf b/website/nginx-example.conf
new file mode 100644
index 00000000..7ebbfa62
--- /dev/null
+++ b/website/nginx-example.conf
@@ -0,0 +1,109 @@
+# AITBC Agent-First Website - Nginx Configuration Example (Live-Only)
+#
+# This configuration serves ONLY live data from the blockchain RPC.
+# No static JSON files - all endpoints query the node in real-time.
+#
+# Requirements:
+# - live_api.py running on port 8080
+# - aitbc-blockchain-rpc service running on port 8006
+#
+# Installation:
+# sudo cp nginx-example.conf /etc/nginx/sites-available/aitbc-agent
+# sudo ln -s /etc/nginx/sites-available/aitbc-agent /etc/nginx/sites-enabled/
+# sudo nginx -t
+# sudo systemctl reload nginx
+
+server {
+ listen 80;
+ listen [::]:80;
+
+ server_name aitbc.bubuit.net localhost;
+
+ # Security headers
+ add_header X-Frame-Options "SAMEORIGIN" always;
+ add_header X-Content-Type-Options "nosniff" always;
+ add_header Referrer-Policy "no-referrer-when-downgrade" always;
+
+ # ============================================
+ # AGENT API - Live-only (real-time from RPC)
+ # ============================================
+ # All agent endpoints proxy to live_api.py service on port 8081
+ # No static files - everything is queried live from blockchain
+
+ location /agent/health {
+ proxy_pass http://127.0.0.1:8081/agent/health;
+ proxy_set_header Host $host;
+ add_header Access-Control-Allow-Origin * always;
+ add_header Cache-Control "no-cache, no-store, must-revalidate" always;
+ }
+
+ location /agent/discovery.json {
+ proxy_pass http://127.0.0.1:8081/agent/discovery.json;
+ proxy_set_header Host $host;
+ add_header Access-Control-Allow-Origin * always;
+ add_header Cache-Control "no-cache, no-store, must-revalidate" always;
+ }
+
+ location /agent/islands.json {
+ proxy_pass http://127.0.0.1:8081/agent/islands.json;
+ proxy_set_header Host $host;
+ add_header Access-Control-Allow-Origin * always;
+ add_header Cache-Control "no-cache, no-store, must-revalidate" always;
+ }
+
+ location /agent/chains.json {
+ proxy_pass http://127.0.0.1:8081/agent/chains.json;
+ proxy_set_header Host $host;
+ add_header Access-Control-Allow-Origin * always;
+ add_header Cache-Control "no-cache, no-store, must-revalidate" always;
+ }
+
+ # Agent landing page (static HTML for human readability)
+ location /agent/ {
+ alias /opt/aitbc/website/agent/;
+ index index.html;
+ try_files $uri $uri/ =404;
+
+ # CORS headers
+ add_header Access-Control-Allow-Origin * always;
+ add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
+ add_header Access-Control-Allow-Headers "Content-Type, Accept" always;
+ }
+
+ # ============================================
+ # RPC ENDPOINTS - Direct blockchain access
+ # ============================================
+ location /rpc/ {
+ proxy_pass http://127.0.0.1:8006/rpc/;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ add_header Access-Control-Allow-Origin * always;
+ add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
+
+ if ($request_method = 'OPTIONS') {
+ return 204;
+ }
+ }
+
+ # ============================================
+ # MAIN WEBSITE - Agent discovery interface
+ # ============================================
+ location / {
+ root /opt/aitbc/website;
+ index index.html;
+ try_files $uri $uri/ =404;
+ }
+
+ # Static assets caching
+ location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
+ expires 1y;
+ add_header Cache-Control "public, immutable";
+ }
+
+ # Logging
+ access_log /var/log/nginx/aitbc-agent.access.log;
+ error_log /var/log/nginx/aitbc-agent.error.log;
+}
diff --git a/website/systemd-example.service b/website/systemd-example.service
new file mode 100644
index 00000000..9394c7ee
--- /dev/null
+++ b/website/systemd-example.service
@@ -0,0 +1,32 @@
+[Unit]
+Description=AITBC Agent Live API
+Documentation=https://github.com/oib/AITBC
+After=aitbc-blockchain-rpc.service
+Wants=aitbc-blockchain-rpc.service
+
+[Service]
+Type=simple
+User=root
+WorkingDirectory=/opt/aitbc/website/agent
+
+# Environment variables - customize for your node
+Environment="AITBC_RPC_URL=http://localhost:8006/rpc"
+Environment="NODE_ID=aitbc"
+Environment="ISLAND_ID=ait-mainnet-island"
+Environment="CHAIN_ID=ait-mainnet"
+Environment="NODE_ROLE=hub"
+Environment="PYTHONUNBUFFERED=1"
+
+# For testnet hub (aitbc1), use these instead:
+# Environment="NODE_ID=aitbc1"
+# Environment="ISLAND_ID=ait-testnet-island"
+# Environment="CHAIN_ID=ait-testnet"
+
+# Python path - update if your venv is elsewhere
+ExecStart=/opt/aitbc/venv/bin/python /opt/aitbc/website/agent/live_api.py --host 127.0.0.1 --port 8081
+
+Restart=always
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target