Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/timepoint-ai/timepoint-clockchain/llms.txt

Use this file to discover all available pages before exploring further.

The Clockchain uses a 3-tier content layer system to progressively enrich nodes with detail. Each layer builds on the previous one, allowing for efficient storage and incremental content generation.

Layer Definitions

LayerContentStorage LocationUse Case
0URL path + event name onlynodes table (id, name)Skeletal graph structure, expansion targets
1Layer 0 + metadatanodes table (tags, figures, one_liner)Browseable events, search results
2Layer 1 + full Flash sceneflash_timepoint_id fieldComplete synthetic time travel experience
Layers are cumulative—Layer 2 includes all content from Layers 0 and 1, plus the full Flash scene reference.

Layer 0: Skeletal Structure

The minimal viable node—just a canonical URL and event name:
{
    "path": "/-44/march/15/1030/italy/lazio/rome/assassination-of-julius-caesar",
    "name": "Assassination of Julius Caesar",
    "layer": 0,
    "visibility": "private"
}

Characteristics

  • Minimal data: Only spatiotemporal coordinates and a name
  • Not publicly browseable: visibility = 'private' by default
  • Expansion targets: Layer 0 nodes are prioritized by the Expander worker
  • Auto-linked: Even at Layer 0, nodes receive automatic edges (contemporaneous, same_location, thematic)
Layer 0 nodes are typically generated by the Expander worker or bulk import processes before full content is available.

Layer 1: Metadata Enrichment

Adds human-readable context without full scene rendering:
{
    "path": "/-44/march/15/1030/italy/lazio/rome/assassination-of-julius-caesar",
    "name": "Assassination of Julius Caesar",
    "layer": 1,
    "visibility": "public",
    "one_liner": "Roman senators assassinate Julius Caesar in the Theatre of Pompey",
    "tags": ["ancient-rome", "political-assassination", "republic"],
    "figures": ["Julius Caesar", "Brutus", "Cassius"]
}

New Fields in Layer 1

FieldTypeDescriptionExample
one_linerStringBrief description (1-2 sentences)"Roman senators assassinate Julius Caesar..."
tagsArrayThematic categories["ancient-rome", "political-assassination"]
figuresArrayKey people involved["Julius Caesar", "Brutus", "Cassius"]

Database Schema

-- From db.py:29-30
tags TEXT[] DEFAULT '{}',
one_liner TEXT DEFAULT '',
figures TEXT[] DEFAULT '{}',
Layer 1 nodes are searchable via the /api/v1/search endpoint, which queries name, one_liner, tags, and figures fields.

Layer 2: Full Flash Scene

Links to a complete Flash scene with dialog, entity states, and narrative:
{
    "path": "/-44/march/15/1030/italy/lazio/rome/assassination-of-julius-caesar",
    "name": "Assassination of Julius Caesar",
    "layer": 2,
    "visibility": "public",
    "one_liner": "Roman senators assassinate Julius Caesar in the Theatre of Pompey",
    "tags": ["ancient-rome", "political-assassination", "republic"],
    "figures": ["Julius Caesar", "Brutus", "Cassius"],
    "flash_timepoint_id": "tp_abc123xyz",
    "flash_slug": "assassination-of-julius-caesar",
    "flash_share_url": "https://app.timepointai.com/moments/tp_abc123xyz"
}

Flash Integration Fields

FieldTypeDescription
flash_timepoint_idStringPrimary reference to Flash scene
flash_slugStringHuman-readable Flash scene identifier
flash_share_urlStringPublic URL for the rendered scene

Database Schema

-- From db.py:32-34
flash_timepoint_id TEXT,
flash_slug TEXT DEFAULT '',
flash_share_url TEXT DEFAULT '',
Layer 2 nodes provide the complete “Synthetic Time Travel” experience—immersive dialog, entity states, source grounding, and confidence scores.

Querying by Layer

The layer field enables filtering nodes by completeness:

Get All Layer 0 Nodes (Expansion Candidates)

SELECT id, name FROM nodes WHERE layer = 0;

Get Browseable Content (Layer 1+)

SELECT * FROM nodes WHERE visibility = 'public' AND layer >= 1;

Get Full Scenes (Layer 2 Only)

SELECT * FROM nodes WHERE layer = 2 AND flash_timepoint_id IS NOT NULL;

Layer Progression Workflow

Nodes typically advance through layers in sequence:

Example: Expander-Generated Node

  1. Expander creates Layer 0 node:
    await graph.add_node(
        node_id="/1969/july/20/2017/united-states/florida/cape-canaveral/apollo-11-moon-landing",
        name="Apollo 11 Moon Landing",
        layer=0,
        source_type="expander"
    )
    
  2. Enrichment (manual or automated) adds metadata → Layer 1:
    await graph.update_node(
        node_id="/1969/july/20/2017/united-states/florida/cape-canaveral/apollo-11-moon-landing",
        layer=1,
        one_liner="First humans land on the Moon",
        tags=["space-exploration", "moon-landing", "nasa"],
        figures=["Neil Armstrong", "Buzz Aldrin", "Michael Collins"]
    )
    
  3. Flash rendering generates full scene → Layer 2:
    await graph.update_node(
        node_id="/1969/july/20/2017/united-states/florida/cape-canaveral/apollo-11-moon-landing",
        layer=2,
        flash_timepoint_id="tp_moon_landing_xyz",
        flash_share_url="https://app.timepointai.com/moments/tp_moon_landing_xyz"
    )
    

Random Public Moments

The /api/v1/random endpoint returns only Layer 1+ nodes:
# From graph.py:271-283
async def random_public(self) -> dict | None:
    async with self.pool.acquire() as conn:
        row = await conn.fetchrow(
            """
            SELECT * FROM nodes
            WHERE visibility = 'public' AND layer >= 1
            ORDER BY random()
            LIMIT 1
            """
        )
    if row is None:
        return None
    return _row_to_dict(row)
This ensures users only see moments with sufficient metadata for a meaningful browsing experience.

Layer Statistics

The /api/v1/stats endpoint provides layer distribution:
# From graph.py:351-353
layer_rows = await conn.fetch(
    "SELECT layer::text AS layer, count(*) AS cnt FROM nodes GROUP BY layer"
)

Example Response

{
  "total_nodes": 1247,
  "layer_counts": {
    "0": 512,
    "1": 489,
    "2": 246
  }
}

Best Practices

  • Layer 0: Use for rapid graph expansion—generate many skeletal nodes first, enrich later
  • Layer 1: Required for public visibility—always add metadata before publishing
  • Layer 2: Reserve for high-value moments that justify the cost of full Flash rendering
  1. Batch enrichment: Generate Layer 0 nodes in bulk, then enrich high-priority nodes to Layer 1
  2. On-demand rendering: Only advance to Layer 2 when a user requests a specific moment
  3. Frontier-first: Prioritize Layer 0 → Layer 1 for frontier nodes (low degree) to maximize graph connectivity

Source Code References

  • Layer validation: app/core/graph.py:26
  • Layer-based queries: app/core/graph.py:271-283 (random), app/api/moments.py (browse)
  • Layer statistics: app/core/graph.py:347-368

Build docs developers (and LLMs) love