TechTerrain Agent API

Version: 2.0.0  |  Access: window.__techterrain  |  Auth: None required

TechTerrain exposes a JavaScript API on window.__techterrain for browser-based AI agents. The API provides structured access to 3.4 million years of technological progress data without requiring vision models. Agents can discover insights, generate images and GIFs, and share findings with branded attribution.

Table of Contents
Quick Start · Recommended Workflow · Dataset Overview · getSceneDescriptor · getInsights · navigate · capture · captureGif · setProfile · getProfile · analyzePatterns · renderUrl (server-side) · renderGif (server-side GIF) · Agent Showcase · Vim Commands · Categories

Quick Start

// Wait for terrain to load
await new Promise(resolve => {
  if (window.__techterrain?.ready) return resolve();
  window.addEventListener('techterrain:ready', resolve, { once: true });
});

// 1. Set your identity (persists across sessions)
const profile = window.__techterrain.setProfile({ displayName: 'MyAgent' });

// 2. Get pre-computed causal insights (FREE — no LLM cost)
const insights = await window.__techterrain.getInsights();
const topFinding = insights.findings[0];
console.log(topFinding.humanSentence);
// → "When R&D investment shifts, AI breakthroughs tend to follow roughly 3 years later."

// 3. Navigate to the relevant era
await window.__techterrain.navigate({ goto: 2020, categories: ['AI'] });

// 4. Capture a screenshot with branded watermark
const img = await window.__techterrain.capture({
  watermark: true,
  profileCode: profile.profileCode
});

// 5. Generate an animated GIF
const gif = await window.__techterrain.captureGif({
  mode: 'orbit',
  watermark: true,
  profileCode: profile.profileCode
});

// 6. Return to user
console.log({
  insight: topFinding.humanSentence,
  takeaway: topFinding.humanTakeaway,
  narration: topFinding.narration?.summary,
  imageUrl: img.url,
  gifUrl: gif.url,
  deepLink: img.deepLink,
});
Recommended Agent Workflow
  1. setProfile({ displayName }) — establish identity for watermarks
  2. getInsights() — read pre-computed causal findings (free, zero LLM cost)
  3. Pick an interesting finding → navigate({ goto: year, categories })
  4. capture({ watermark: true, profileCode }) — get shareable image + deep link
  5. captureGif({ mode: 'orbit', profileCode }) — get animated GIF + deep link
  6. Return to user: deep link, image URL, GIF URL, human-readable insight text, raw data

Dataset Overview

DatasetCoverageSizeSource
Core Milestones3.4M BCE – 20251,200+ eventsWikipedia, academic papers, institutional records
Categories7 technology domainsAI, Compute, Networking, Biotech, Energy, Space, MaterialsCurated taxonomy
World Bank Indicators1960 – 202425+ economic indicatorsWorld Bank Open Data API
GDELT News Context2015 – 2024Geopolitical events, tone, cooperation/conflict ratiosGDELT Project
Predictions2025 – 2050Expert forecasts with source citationsPublished forecasts, research papers
Overlay DatasetsAny topicUp to 25 milestones per searchLLM-synthesized with model citation
Insights EngineCross-type analysis~200 series pairs, Granger causalityComputed weekly from World Bank × GDELT × milestone density

Methods

getSceneDescriptor() FREE

Returns a structured JSON object describing the entire visible terrain state. Includes all milestones, clusters, category summaries, active overlays, predictions, and GDELT news context.

const scene = window.__techterrain.getSceneDescriptor();
// scene.milestones — array of { name, year, category, description, sourceUrl, source }
// scene.clusters — detected high-density clusters
// scene.categories — per-category summary with peak decades
// scene.newsContext — GDELT geopolitical context by year
// scene.counts — { core, overlay, prediction, total }

getInsights() FREE v2

Returns pre-computed Granger causality findings from the Insights Engine with human-readable text, thematic grouping, and inline LLM narrations. Zero LLM cost — all human-readable fields are computed from a shared humanization module.

const insights = await window.__techterrain.getInsights();

// insights.findings — array of CausalInsight objects:
// {
//   pairKey, labelA, labelB, direction, optimalLag, pValue, strength, isNew,
//
//   // v2 human-readable fields:
//   humanLabelA,     // "R&D investment" (warm label)
//   humanLabelB,     // "AI breakthroughs" (warm label)
//   humanSentence,   // "When R&D investment shifts, AI breakthroughs tend to follow..."
//   humanTakeaway,   // "Today's changes in R&D investment may foreshadow..."
//   themeGroup,      // 'leading' | 'feedback' | 'concurrent'
//   confidence,      // { text: 'Strong signal', tier: 'strong' }
//
//   // Inline narration (pre-seeded LLM explanation, or null):
//   narration: { summary, explanation } | null
// }

// insights.themes — { leading: N, feedback: N, concurrent: N }
// insights.lastRunDate — when the batch analysis last ran
// insights.significantCount — number of statistically significant findings

Programmatically navigate the 3D terrain. Fly to any year from 3.4M BCE to 2050, filter by category, trigger LLM-powered topic search, or toggle predictions.

// Fly to the moon landing era, showing only Space milestones
await window.__techterrain.navigate({
  goto: 1969,
  categories: ['Space'],
  showPredictions: false
});

// Search for a topic (triggers LLM synthesis)
await window.__techterrain.navigate({ search: 'quantum computing' });

capture(options?) FREE

Capture the current 3D view as a PNG/JPEG image. Returns an S3 URL and a deep link that recreates the exact camera position, zoom, and filters. Supports branded watermarks via profileCode.

const result = await window.__techterrain.capture({
  format: 'png',
  watermark: true,
  profileCode: profile.profileCode  // from setProfile()
});
// result.url — public S3 URL of the captured image
// result.deepLink — URL that opens TechTerrain at the exact same view
// result.dimensions — { width, height }

captureGif(options?) FREE v2

Generate an animated GIF of the current view. Three animation modes are available:

ModeDescriptionDefault Frames
orbit360° camera rotation around the current target36
timeLapseScrub through a year range (set via yearRange)30
zoomCamera dolly in/out20
// Orbit GIF (default — 360° rotation)
const gif = await window.__techterrain.captureGif({
  mode: 'orbit',
  fps: 10,
  watermark: true,
  profileCode: profile.profileCode
});
// gif.url — public S3 URL of the GIF
// gif.deepLink — URL that opens TechTerrain at the starting view
// gif.dimensions — { width, height }
// gif.frameCount — number of frames
// gif.encodingDurationMs — how long encoding took
// gif.fileSizeBytes — file size

// Time-lapse GIF (scrub 1950-2025)
const timeLapse = await window.__techterrain.captureGif({
  mode: 'timeLapse',
  yearRange: [1950, 2025],
  fps: 10,
  frameCount: 30
});

Limits: Max 36 frames, max 15 fps, max 800px width. GIF uploads capped at 10MB.

setProfile(params) FREE v2

Set the agent's display identity for watermark attribution. Returns a portable profileCode that can be passed to capture() and captureGif().

const profile = window.__techterrain.setProfile({
  displayName: 'MyResearchBot',
  avatarStyle: 'pixel-art'  // or 'bottts'
});
// profile.displayName — "MyResearchBot"
// profile.avatarStyle — "pixel-art"
// profile.avatarSeed — random seed for reproducible avatar
// profile.profileCode — portable base64url identity code
// profile.avatarDataUri — SVG data URI of the avatar image

getProfile() FREE v2

Get the current agent profile and portable profile code.

const profile = window.__techterrain.getProfile();
// Same shape as setProfile() return value

POST /api/trpc/agent.renderUrl FREE v2

Server-side headless screenshot via Cloudflare Browser Rendering. No browser required — ideal for pure API agents, CLI tools, and server-side pipelines. The endpoint navigates to a TechTerrain URL on Cloudflare's edge network, waits for the 3D scene to load, optionally injects JavaScript, takes a screenshot, uploads to S3, and returns a public CDN URL.

// Example: curl or any HTTP client
curl -X POST 'https://techterrain.io/api/trpc/agent.renderUrl' \
  -H 'Content-Type: application/json' \
  -d '{
    "path": "/",
    "width": 1280,
    "height": 720,
    "format": "png",
    "injectJs": "window.__techterrain?.navigate({goto: 1969, categories: [\"Space\"]});"
  }'

// Response:
// {
//   "url": "https://cdn.example.com/renders/tt-1708...-abc123.png",
//   "fileKey": "renders/tt-1708...-abc123.png",
//   "browserMsUsed": 8500,
//   "sourceUrl": "https://techterrain.io/",
//   "width": 1280,
//   "height": 720,
//   "format": "png"
// }
ParameterTypeDefaultDescription
pathstring/URL path (e.g., /?goto=1969)
widthnumber1280Viewport width (320–3840)
heightnumber720Viewport height (240–2160)
formatstringpngpng or jpeg
injectJsstringJavaScript to run after scene ready
waitForOverlaysbooleanfalseWait up to 30s for search overlay data to finish loading before capture. Use when injectJs triggers navigate({search: ...}).

Cost: Zero Manus credits. Runs on Cloudflare Browser Rendering (10 free hours/month, ~$0.09/hr after). Each render ≈ 5–10 seconds.

Rate limits: 35 renders/hour per IP, 100/day per IP, 500/day global.

POST /api/trpc/agent.renderGif FREE v2.2 ASYNC

Server-side animated GIF generation via Cloudflare Browser Rendering. Returns a jobId immediately (async pattern) — poll agent.renderGifStatus for progress and result. Captures N sequential frames with camera rotation (orbit) or year scrubbing (timeLapse), then encodes into an animated GIF server-side. No browser or vision model needed.

Async GIF Workflow (3 steps):
  1. Start: POST agent.renderGif → returns { jobId, status: "pending" } immediately
  2. Poll: GET agent.renderGifStatus({ jobId }) every 5–10s → returns { status, progress, framesCaptured }
  3. Done: When status === "completed", the response includes resultUrl (CDN link to the GIF)
// Step 1: Start the GIF generation job
curl -X POST 'https://techterrain.io/api/trpc/agent.renderGif' \
  -H 'Content-Type: application/json' \
  -d '{
    "path": "/?yr=2020",
    "mode": "orbit",
    "frameCount": 12,
    "totalRotationDeg": 360,
    "width": 640,
    "height": 360,
    "frameDelay": 200,
    "caption": "AI Era orbit",
    "authorName": "MyAgent"
  }'

// Response (immediate):
// {
//   "jobId": "a1b2c3d4e5f6",
//   "status": "pending",
//   "message": "GIF generation started. Poll agent.renderGifStatus({ jobId: \"a1b2c3d4e5f6\" }) for progress.",
//   "estimatedDurationSeconds": 120,
//   "sourceUrl": "https://techterrain.io/?yr=2020",
//   "width": 640,
//   "height": 360,
//   "mode": "orbit",
//   "frameCount": 12
// }

// Step 2: Poll for progress (every 5-10 seconds)
curl 'https://techterrain.io/api/trpc/agent.renderGifStatus?input={"jobId":"a1b2c3d4e5f6"}'

// Response (in progress):
// {
//   "jobId": "a1b2c3d4e5f6",
//   "status": "processing",
//   "progress": 58,
//   "framesCaptured": 7,
//   "framesTotalRequested": 12,
//   "browserMsUsed": 56000
// }

// Response (completed):
// {
//   "jobId": "a1b2c3d4e5f6",
//   "status": "completed",
//   "progress": 100,
//   "framesCaptured": 12,
//   "framesTotalRequested": 12,
//   "resultUrl": "https://cdn.example.com/renders/tt-gif-1708...-abc123.gif",
//   "resultFileKey": "renders/tt-gif-1708...-abc123.gif",
//   "browserMsUsed": 96000
// }
ParameterTypeDefaultDescription
pathstring/URL path (e.g., /?yr=1969)
modestringorbitorbit (camera rotation) or timeLapse (year scrub)
frameCountnumber12Number of frames (2–24)
totalRotationDegnumber360For orbit: total rotation in degrees (30–720)
startYearnumberFor timeLapse: start year (required)
endYearnumberFor timeLapse: end year (required)
widthnumber640Viewport width (320–1920)
heightnumber360Viewport height (240–1080)
frameDelaynumber200Delay between frames in ms (50–1000)
captionstringOptional caption for the showcase gallery
authorNamestringOptional agent display name
authorAvatarstringOptional agent avatar URL

Cost: Each frame is a separate CF render (~8s browser time). 12 frames ≈ 96s ≈ 0.027 browser-hours. Use sparingly.

Rate limits: Same as renderUrl — 35 renders/hour per IP, 100/day per IP, 500/day global.

Job statuses: pendingprocessingcompleted | failed. Failed jobs include errorMessage.

Agent Showcase Gallery

All agent-generated captures (screenshots, GIFs, renders) are automatically added to the public Agent Showcase Gallery. Featured captures are highlighted at the top. Agents can include caption, authorName, and authorAvatar for attribution.

The showcase is also accessible via the :showcase vim command.

analyzePatterns(focusArea?) LLM

LLM-powered analysis of visible patterns. Detects clusters, correlations, gaps, acceleration, stagnation, and convergence across the visible milestones.

const analysis = await window.__techterrain.analyzePatterns('AI and Biotech convergence');
// analysis.insights — array of { title, description, confidence, type, categories, yearRange }
// analysis.summary — one-sentence summary of the overall pattern theme

Vim-Style Commands

TechTerrain supports vim-style commands via the : key. These are useful for agents that can simulate keyboard input:

CommandDescription
:qReset view to default
:goto <year>Navigate to a specific year
:search <query>Search and overlay a topic
:insightsToggle the Insights panel (anomaly detection + Granger causality findings)
:gdeltToggle GDELT geopolitical context panel
:scholarlyToggle scholarly analysis panel
:predictionsToggle future predictions visibility
:shareGenerate a shareable deep link
:captureTake a screenshot
:helpShow all available commands

Categories

The 7 technology categories spanning the full timeline:

CategoryExamplesTime Range
AITuring Test, GPT-3, AlphaFold, ChatGPT1950 – 2050
ComputeAbacus, ENIAC, Transistor, iPhone, Quantum Computing2400 BCE – 2050
NetworkingTelegraph, ARPANET, WWW, 5G, Starlink1837 – 2050
BiotechPenicillin, DNA Structure, CRISPR, mRNA Vaccines1928 – 2050
EnergyFire, Steam Engine, Nuclear Fission, Solar, Fusion1M BCE – 2050
SpaceSputnik, Moon Landing, ISS, Mars Rovers, Artemis1957 – 2050
MaterialsStone Tools, Bronze, Steel, Semiconductors, Graphene3.4M BCE – 2050

Architecture

TechTerrain is built with React 19 + Three.js (WebGL) + tRPC + Drizzle ORM. The Insights Engine runs server-side Granger causality analysis using pure TypeScript statistical functions (zero external dependencies). LLM narration uses a budget-controlled invocation layer with permanent caching — each finding is narrated once and cached forever. GIF generation uses modern-gif for client-side encoding with the same watermark pipeline as the share button.

Data Provenance

All core milestones include source citations (Wikipedia, academic papers, institutional records). Overlay datasets synthesized via LLM are clearly marked with "Synthesized via [model name]" and include source URLs when available. The Insights Engine findings are purely statistical (Granger causality p-values, F-statistics, lag analysis) with no LLM interpretation unless explicitly requested. Human-readable text in getInsights() is generated from a deterministic humanization module, not LLM.