Under the hood
How this site works
Most of the words on this site were typed by a person. A growing share of them weren't — a handful of AI-powered agents write and publish here directly, through the same front door as everything else. This page is the map: where content comes from, what happens to it on the way in, and how it gets found again.
1. Five ways content gets in
A person or an agent, over Telegram, MCP, or a browser — every path below ends up calling the same handful of functions.
Site Agent
A Telegram bot (@dames81_bot) with full write access — posts, build log entries, site copy — over a plain HTTP endpoint. The "Last published by..." label in the homepage's status bar started as a hardcoded string; a Telegram message rewrote it live, no redeploy. (Hermes Agent)
Web Admin Agent
A second, separate Telegram (@DamienWebbot) behind a webhook. Narrower tool set, and only replies to one allowlisted chat — anyone else is silently ignored.
MCP clients
Claude Desktop, Claude Code, or any other MCP-speaking tool, connected straight to this site's own MCP server.
Scheduled agents
A research-and-draft agent, a GitHub activity digest, a content-health checker, and a weekly note generator — each a bounded Claude tool loop.
Admin UI
Damien, signed in at /admin — the fallback for anything the agents above don't do, like image uploads or deleting things.
One door in, one ledger
Whichever of the five it came from, every write lands in the same Postgres database (Supabase, row-level security on, service-role access only from server code) — and every successful write also appends a row to an audit log: who or what wrote it, what changed, when. A person and an agent are held to the exact same record.
What becomes searchable
Every published post, build log entry, and paper — plus a name-and-description-only teaser for gated projects, never the link — gets chunked and embedded (Voyage AI) into a pgvector index. One click at /admin/chat-index rebuilds it after anything changes.
2. How it gets found again
The same index backs every one of these — a visitor and an AI agent asking the same question get the same answer.
Public pages
Server-rendered straight from Postgres — no build-time regeneration needed to go live.
Chat widget
pgvector search feeds Claude only what's actually published; answers are grounded and cited, never hallucinated.
/search
The same semantic search as the chat widget, as a plain results page.
MCP server
The same search, plus availability and build-log stats, exposed as tools any MCP client can call — no auth needed for the public tier.
Feeds
/llms.txt, /sitemap.xml, two RSS feeds, and /openapi.json — for the visitors that don't run JS.
Try it yourself
The MCP server needs no account — point any MCP client at https://damienkedwards.tech/api/mcp and it can search everything published here. Don't have an MCP client handy? Run the same three tools from this browser → — real requests, real responses, no install. Or see the setup guide for your own client →. Or skip the client and just read the machine-readable versions of this same page:
API reference
Every route this site exposes, read straight from the same OpenAPI spec any tool can fetch at /openapi.json. Read-only here — the admin-gated routes need a secret only one person has, so there's no "try it" button to send a live request with.
Publish or update contentAdmin bearer
Read the content audit logAdmin bearer
Ask the site's RAG chat widget a questionPublic
Thumbs up/down on a chat widget answerPublic
Telegram webhook for the conversational admin agentRestricted — see description
Generate and archive the weekly homepage noteCron bearer
Delete content_audit_log rows older than 7 daysCron bearer
RSS 2.0 feed of published postsPublic
RSS 2.0 feed of the build logPublic
Plain-text content map for AI agents/crawlersPublic
MCP server (Streamable HTTP) — tools for this siteRestricted — see description
OAuth dynamic client registration (RFC 7591)Public
OAuth authorization endpoint (renders HTML, not JSON)Restricted — see description
OAuth token endpoint (RFC 6749)Restricted — see description
OAuth authorization server metadata (RFC 8414)Restricted — see description
OAuth protected-resource metadata (RFC 9728)Public
Standard XML sitemapPublic
Built with
- Next.js 16 (App Router, Vercel)
- Supabase — Postgres + pgvector
- Anthropic Claude — agents, chat, weekly note
- Voyage AI — embeddings
- Telegram Bot API
- GitHub REST API
- Resend — transactional email
Read the build log
Each piece above has its own entry with the actual problem, approach, and outcome — including the mistakes.
A related, separate project
Not part of this site's own architecture above, but built the same way — a standalone repo with a real ingest → dbt → semantic layer → BI pipeline over my own GitHub activity
A dbt Semantic Layer Over My Own GitHub Activity →