{
  "site": {
    "name": "Lyóvson.com",
    "description": "Official website of Rafa and Jess Lyóvson",
    "url": "https://www.lyovson.com",
    "authors": [
      "Rafa Lyóvson",
      "Jess Lyóvson"
    ],
    "topics": [
      "programming",
      "design",
      "philosophy",
      "technology",
      "research"
    ],
    "contentStats": {
      "totalPosts": 1,
      "totalProjects": 1,
      "totalTopics": 1,
      "totalNotes": 1,
      "totalActivities": 1,
      "totalAuthors": 1
    }
  },
  "openapi": "3.1.0",
  "contentAccess": {
    "description": "All content is accessible via standard HTTP GET requests to documented endpoints",
    "api": {
      "type": "REST",
      "description": "RESTful API for accessing posts, projects, topics, notes, and activities",
      "rest": {
        "endpoints": [
          {
            "path": "/",
            "method": "GET",
            "description": "Homepage with latest posts and featured projects",
            "response": "HTML page",
            "access": "public"
          },
          {
            "path": "/posts/{postSlug}",
            "method": "GET",
            "description": "Individual post pages",
            "parameters": {
              "postSlug": "URL-friendly post identifier"
            },
            "response": "HTML page with full post content",
            "access": "public"
          },
          {
            "path": "/api/docs",
            "method": "GET",
            "description": "API documentation (this endpoint)",
            "response": "JSON",
            "access": "public",
            "caching": "3600s"
          }
        ]
      }
    },
    "collections": {
      "description": "Content organized into collections accessible through Payload CMS",
      "available": [
        {
          "name": "posts",
          "endpoint": "https://www.lyovson.com/posts",
          "description": "Blog posts and articles",
          "fields": [
            "title",
            "content",
            "authors",
            "project",
            "topics",
            "meta"
          ],
          "access": "published posts are public",
          "sorting": "newest first by default"
        },
        {
          "name": "projects",
          "endpoint": "https://www.lyovson.com/projects",
          "description": "Project collections and categories",
          "fields": [
            "name",
            "slug",
            "description"
          ],
          "access": "public"
        },
        {
          "name": "topics",
          "endpoint": "https://www.lyovson.com/topics",
          "description": "Content categorization tags",
          "fields": [
            "name",
            "description",
            "color"
          ],
          "access": "public"
        },
        {
          "name": "notes",
          "endpoint": "https://www.lyovson.com/notes",
          "description": "Short-form notes, quotes, and reflections",
          "fields": [
            "title",
            "content",
            "author",
            "type",
            "topics"
          ],
          "access": "published public notes are accessible"
        },
        {
          "name": "activities",
          "endpoint": "https://www.lyovson.com/activities",
          "description": "Reading, watching, listening, and playing activity logs",
          "fields": [
            "reference",
            "activityType",
            "participants",
            "notes",
            "startedAt",
            "finishedAt"
          ],
          "access": "published public activities are accessible"
        },
        {
          "name": "authors",
          "endpoint": "https://www.lyovson.com/{username}",
          "description": "Public author profile and bio pages",
          "fields": [
            "name",
            "username",
            "bio",
            "socialLinks"
          ],
          "access": "public profile routes; underlying user collection is private"
        }
      ]
    },
    "embeddings": {
      "description": "Semantic search using pgvector embeddings for posts, notes, and activities",
      "model": "text-embedding-3-small (OpenAI)",
      "dimensions": 1536,
      "endpoints": {
        "embeddings": {
          "path": "/api/embeddings",
          "methods": {
            "bulk": {
              "description": "Get embeddings for multiple items (posts, activities, notes)",
              "parameters": {
                "type": "posts | activities | notes | all (optional, defaults to 'all')",
                "limit": "number (optional, max 100, defaults to 50)",
                "vector": "boolean (optional, include vector data, defaults to true)",
                "content": "boolean (optional, include full content, defaults to false)"
              },
              "examples": [
                "https://www.lyovson.com/api/embeddings?type=posts&limit=10",
                "https://www.lyovson.com/api/embeddings?type=activities&vector=false",
                "https://www.lyovson.com/api/embeddings?type=all&limit=25"
              ],
              "caching": "3600s",
              "notes": "Returns pre-computed embeddings only for fast response times"
            },
            "specific": {
              "description": "Get embedding for a specific item by ID",
              "parameters": {
                "type": "posts | activities | notes (required)",
                "id": "item ID (required)"
              },
              "example": "https://www.lyovson.com/api/embeddings?type=posts&id=123",
              "caching": "3600s"
            },
            "query": {
              "description": "Generate embedding for a text query (on-demand, disabled for public by default)",
              "parameters": {
                "q": "text query (required)"
              },
              "example": "https://www.lyovson.com/api/embeddings?q=programming+philosophy",
              "caching": "3600s",
              "notes": "Requires admin auth/CRON_SECRET unless ENABLE_PUBLIC_QUERY_EMBEDDINGS=true"
            }
          }
        },
        "sync": {
          "path": "/api/embeddings/sync",
          "description": "Batch-generate stale/missing embeddings (designed for daily cron)",
          "method": "POST",
          "auth": "admin session or Bearer CRON_SECRET"
        },
        "status": {
          "path": "/api/embeddings/status",
          "description": "Get embedding system health and coverage statistics",
          "response": {
            "system": "health status and configuration",
            "statistics": "coverage percentages per collection",
            "recommendations": "actionable improvement suggestions"
          },
          "caching": "300s"
        },
        "search": {
          "path": "/api/search",
          "description": "Semantic search across all content using embeddings, with optional person scoping and preview payloads",
          "parameters": {
            "q": "search query (required)",
            "limit": "number of results (optional, defaults to 10)",
            "scope": "person scope username such as rafa or jess (optional)",
            "preview": "when true, includes compact previewItems for nav/live-preview UI (optional)"
          },
          "example": "https://www.lyovson.com/api/search?q=web+development&limit=5&scope=rafa",
          "response": "ranked results with similarity scores, plus previewItems when preview=true",
          "caching": "300s"
        }
      },
      "features": [
        "Pre-computed embeddings for fast bulk access",
        "Batched embedding sync for stale/missing content",
        "Optional on-demand query embeddings (auth-gated by default)",
        "HNSW expression indexes for casted vector search",
        "Cosine similarity ranking",
        "Collection-specific coverage tracking"
      ],
      "storage": "PostgreSQL with pgvector extension",
      "indexing": "HNSW on embedding_vector::vector(1536)"
    }
  },
  "dataFormat": {
    "posts": {
      "structure": "Lexical rich text format (JSON)",
      "features": [
        "Nested block structure",
        "Custom components (banners, code blocks, media)",
        "Relationship links to other content",
        "Version control via _status field"
      ],
      "serialization": {
        "internal": "Lexical JSON",
        "public": "Converted to HTML/Markdown for display"
      }
    },
    "notes": {
      "structure": "Lexical rich text format (JSON)",
      "features": [
        "Short-form thought and quote content",
        "Topic relationships",
        "Connection graph to posts/references/notes"
      ],
      "serialization": {
        "internal": "Lexical JSON",
        "public": "Rendered HTML with card summaries"
      }
    },
    "activities": {
      "structure": "Structured activity metadata + optional rich text notes",
      "features": [
        "Activity type (read/watch/listen/play/visit)",
        "Reference relationships",
        "Participant relationships",
        "Timeline fields (startedAt/finishedAt/publishedAt)"
      ],
      "serialization": {
        "internal": "Payload document fields + Lexical JSON for notes",
        "public": "Rendered activity pages with stable date+slug URLs"
      }
    }
  },
  "rateLimits": {
    "default": "No explicit limits in development",
    "production": "Subject to Vercel edge function limits",
    "caching": "Aggressive caching via Cache-Control headers"
  },
  "metadata": {
    "framework": "Next.js 16 with App Router",
    "cms": "Payload CMS 3.x",
    "database": "Vercel Postgres with pgvector",
    "hosting": "Vercel",
    "search": "Semantic search via OpenAI embeddings"
  },
  "usage": {
    "aiAgents": {
      "description": "This API is designed for AI agents to understand and access site content",
      "recommendations": [
        "Use /api/docs to understand available endpoints",
        "Use /api/embeddings for semantic search",
        "Use /api/search for natural language queries",
        "Use /api/embeddings/status to check system health",
        "Access individual posts via /posts/{postSlug}",
        "Respect Cache-Control headers for optimal performance"
      ],
      "bestPractices": [
        "Start with /api/search for content discovery",
        "Use embeddings similarity scores to rank relevance",
        "Use scope=rafa or scope=jess when search should stay within one person mode",
        "Filter by topics for focused content areas",
        "Check embedding coverage before bulk operations",
        "Use vector=false parameter when vectors aren't needed"
      ]
    },
    "humanDevelopers": {
      "description": "Standard REST API access patterns apply",
      "recommendations": [
        "All GET endpoints return JSON",
        "CORS enabled for public endpoints",
        "Standard HTTP status codes (200, 404, 500)",
        "Errors include descriptive messages"
      ]
    }
  },
  "contact": {
    "general": "hello@lyovson.com",
    "technical": "rafa@lyovson.com",
    "github": "https://github.com/rafalyovson"
  },
  "links": {
    "documentation": "https://www.lyovson.com/api/docs",
    "embeddingStatus": "https://www.lyovson.com/api/embeddings/status",
    "search": "https://www.lyovson.com/api/search",
    "home": "https://www.lyovson.com"
  },
  "version": "3.0.0",
  "lastUpdated": "2026-04-22T22:54:11.811Z"
}