# tedawf/tacos architecture

> Architecture diagram of the GitHub repository tedawf/tacos, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-26). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/tedawf/tacos
- Repository: https://github.com/tedawf/tacos

## Overview

TACOS is a FastAPI backend for Obsidian/CouchDB content sync, a blog and image API, and RAG-based portfolio chat/search. Its main content path is CouchDB change listening, parsing and chunking documents, embedding them, then storing vectors in Postgres; its query path retrieves relevant content and streams an OpenAI response. The blog API separately reads posts and view counts from CouchDB and Postgres. The README documents these capabilities; some subsystem wiring is inferred from the documented behavior because its implementation was not sampled.

Main entry points: [`app/services/docs_ingester.py`](https://github.com/tedawf/tacos/blob/main/app/services/docs_ingester.py) (Document ingester), [`app/services/rag_service.py`](https://github.com/tedawf/tacos/blob/main/app/services/rag_service.py) (RAG service), [`app/services/posts_service.py`](https://github.com/tedawf/tacos/blob/main/app/services/posts_service.py) (Posts service), [`app/db/postgres/base.py`](https://github.com/tedawf/tacos/blob/main/app/db/postgres/base.py) (Postgres pgvector)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_sync["Content Sync"]
  node_listener["Change listener"]
  node_ingester["Document ingester<br/>[docs_ingester.py]"]
  node_parser["Content parser<br/>[content_parser.py]"]
  node_enhancer["Content enhancer"]
  node_embedder["Text embedder<br/>[text_embedder.py]"]
end

subgraph group_blog["Blog API"]
  node_posts_router["Posts endpoints<br/>[posts.py]"]
  node_posts_service["Posts service<br/>[posts_service.py]"]
  node_posts_repo["Couch posts repo<br/>[posts_repo.py]"]
  node_views["Post view service"]
  node_images_router["Image endpoint<br/>[images.py]"]
  node_images["Image service<br/>[image_service.py]"]
end

subgraph group_rag["RAG Chat"]
  node_rag_router["RAG endpoints<br/>[rag.py]"]
  node_rag_service["RAG service<br/>[rag_service.py]"]
  node_expander["Query expander<br/>[query_expander.py]"]
  node_chat_logger["Chat logger<br/>[chat_logger.py]"]
end

subgraph group_state["Persistence"]
  node_postgres[("Postgres pgvector<br/>[base.py]")]
  node_docs["Document model<br/>[doc.py]"]
  node_chat_model["Chat history model<br/>[chat.py]"]
  node_views_model["Post views model<br/>[post_view.py]"]
end

node_obsidian(("Obsidian LiveSync"))
node_couchdb[("CouchDB")]
node_api["FastAPI app<br/>[main.py]"]
node_visitor(("Site visitors"))
node_openai{{"OpenAI API"}}

node_obsidian -->|"syncs content"| node_couchdb
node_api -->|"starts listener"| node_listener
node_listener -->|"reads changes"| node_couchdb
node_listener -->|"dispatches docs"| node_ingester
node_ingester -->|"parses markdown"| node_parser
node_ingester -->|"enhances chunks"| node_enhancer
node_ingester -->|"embeds chunks"| node_embedder
node_ingester -->|"writes vectors"| node_postgres
node_visitor -->|"requests posts"| node_posts_router
node_posts_router -->|"delegates"| node_posts_service
node_posts_service -->|"loads posts"| node_posts_repo
node_posts_repo -->|"reads documents"| node_couchdb
node_posts_service -->|"parses content"| node_parser
node_posts_service -->|"loads counts"| node_views
node_views -->|"reads counts"| node_postgres
node_visitor -->|"requests image"| node_images_router
node_images_router -->|"serves image"| node_images
node_images -->|"reads image"| node_couchdb
node_visitor -->|"asks question"| node_rag_router
node_rag_router -->|"searches and streams"| node_rag_service
node_rag_router -->|"records turns"| node_chat_logger
node_rag_service -->|"expands query"| node_expander
node_rag_service -->|"embeds query"| node_embedder
node_rag_service -->|"searches vectors"| node_postgres
node_rag_service -->|"streams answer"| node_openai
node_chat_logger -->|"stores history"| node_postgres
node_chat_logger -->|"persists messages"| node_chat_model
node_posts_service -->|"counts views"| node_views_model
node_ingester -->|"stores chunks"| node_docs
node_rag_service -->|"retrieves context"| node_docs

click node_api "https://github.com/tedawf/tacos/blob/main/app/main.py"
click node_listener "https://github.com/tedawf/tacos/blob/main/app/services/couchdb_listener.py"
click node_ingester "https://github.com/tedawf/tacos/blob/main/app/services/docs_ingester.py"
click node_parser "https://github.com/tedawf/tacos/blob/main/app/services/content_parser.py"
click node_enhancer "https://github.com/tedawf/tacos/blob/main/app/services/content_enhancer.py"
click node_embedder "https://github.com/tedawf/tacos/blob/main/app/services/text_embedder.py"
click node_posts_router "https://github.com/tedawf/tacos/blob/main/app/routers/posts.py"
click node_posts_service "https://github.com/tedawf/tacos/blob/main/app/services/posts_service.py"
click node_posts_repo "https://github.com/tedawf/tacos/blob/main/app/repos/posts_repo.py"
click node_views "https://github.com/tedawf/tacos/blob/main/app/services/post_view_service.py"
click node_images_router "https://github.com/tedawf/tacos/blob/main/app/routers/images.py"
click node_images "https://github.com/tedawf/tacos/blob/main/app/services/image_service.py"
click node_rag_router "https://github.com/tedawf/tacos/blob/main/app/routers/rag.py"
click node_rag_service "https://github.com/tedawf/tacos/blob/main/app/services/rag_service.py"
click node_expander "https://github.com/tedawf/tacos/blob/main/app/services/query_expander.py"
click node_chat_logger "https://github.com/tedawf/tacos/blob/main/app/services/chat_logger.py"
click node_postgres "https://github.com/tedawf/tacos/blob/main/app/db/postgres/base.py"
click node_docs "https://github.com/tedawf/tacos/blob/main/app/models/doc.py"
click node_chat_model "https://github.com/tedawf/tacos/blob/main/app/models/chat.py"
click node_views_model "https://github.com/tedawf/tacos/blob/main/app/models/post_view.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_listener,node_ingester,node_parser,node_enhancer,node_embedder toneBlue
class node_posts_router,node_posts_service,node_posts_repo,node_views,node_images_router,node_images,node_couchdb toneAmber
class node_rag_router,node_rag_service,node_expander,node_chat_logger,node_api,node_openai toneMint
class node_postgres,node_docs,node_chat_model,node_views_model toneRose
class node_obsidian,node_visitor toneIndigo
```

## Components

### Content Sync

- [Change listener](https://github.com/tedawf/tacos/blob/main/app/services/couchdb_listener.py): `app/services/couchdb_listener.py`
- [Document ingester](https://github.com/tedawf/tacos/blob/main/app/services/docs_ingester.py): `app/services/docs_ingester.py`
- [Content parser](https://github.com/tedawf/tacos/blob/main/app/services/content_parser.py): `app/services/content_parser.py`
- [Content enhancer](https://github.com/tedawf/tacos/blob/main/app/services/content_enhancer.py): `app/services/content_enhancer.py`
- [Text embedder](https://github.com/tedawf/tacos/blob/main/app/services/text_embedder.py): `app/services/text_embedder.py`

### Blog API

- [Posts endpoints](https://github.com/tedawf/tacos/blob/main/app/routers/posts.py): `app/routers/posts.py`
- [Posts service](https://github.com/tedawf/tacos/blob/main/app/services/posts_service.py): `app/services/posts_service.py`
- [Couch posts repo](https://github.com/tedawf/tacos/blob/main/app/repos/posts_repo.py): `app/repos/posts_repo.py`
- [Post view service](https://github.com/tedawf/tacos/blob/main/app/services/post_view_service.py): `app/services/post_view_service.py`
- [Image endpoint](https://github.com/tedawf/tacos/blob/main/app/routers/images.py): `app/routers/images.py`
- [Image service](https://github.com/tedawf/tacos/blob/main/app/services/image_service.py): `app/services/image_service.py`

### RAG Chat

- [RAG endpoints](https://github.com/tedawf/tacos/blob/main/app/routers/rag.py): `app/routers/rag.py`
- [RAG service](https://github.com/tedawf/tacos/blob/main/app/services/rag_service.py): `app/services/rag_service.py`
- [Query expander](https://github.com/tedawf/tacos/blob/main/app/services/query_expander.py): `app/services/query_expander.py`
- [Chat logger](https://github.com/tedawf/tacos/blob/main/app/services/chat_logger.py): `app/services/chat_logger.py`

### Persistence

- [Postgres pgvector](https://github.com/tedawf/tacos/blob/main/app/db/postgres/base.py): `app/db/postgres/base.py`
- [Document model](https://github.com/tedawf/tacos/blob/main/app/models/doc.py): `app/models/doc.py`
- [Chat history model](https://github.com/tedawf/tacos/blob/main/app/models/chat.py): `app/models/chat.py`
- [Post views model](https://github.com/tedawf/tacos/blob/main/app/models/post_view.py): `app/models/post_view.py`

### Other components

- **Obsidian LiveSync**
- **CouchDB**
- [FastAPI app](https://github.com/tedawf/tacos/blob/main/app/main.py): `app/main.py`
- **Site visitors**
- **OpenAI API**

## Connections

- Obsidian LiveSync → CouchDB: syncs content
- FastAPI app → Change listener: starts listener
- Change listener → CouchDB: reads changes
- Change listener → Document ingester: dispatches docs
- Document ingester → Content parser: parses markdown
- Document ingester → Content enhancer: enhances chunks
- Document ingester → Text embedder: embeds chunks
- Document ingester → Postgres pgvector: writes vectors
- Site visitors → Posts endpoints: requests posts
- Posts endpoints → Posts service: delegates
- Posts service → Couch posts repo: loads posts
- Couch posts repo → CouchDB: reads documents
- Posts service → Content parser: parses content
- Posts service → Post view service: loads counts
- Post view service → Postgres pgvector: reads counts
- Site visitors → Image endpoint: requests image
- Image endpoint → Image service: serves image
- Image service → CouchDB: reads image
- Site visitors → RAG endpoints: asks question
- RAG endpoints → RAG service: searches and streams
- RAG endpoints → Chat logger: records turns
- RAG service → Query expander: expands query
- RAG service → Text embedder: embeds query
- RAG service → Postgres pgvector: searches vectors
- RAG service → OpenAI API: streams answer
- Chat logger → Postgres pgvector: stores history
- Chat logger → Chat history model: persists messages
- Posts service → Post views model: counts views
- Document ingester → Document model: stores chunks
- RAG service → Document model: retrieves context
