# https://github.com/zcag/tela Project Manual

Generated at: 2026-07-05 04:32:40 UTC

## Table of Contents

- [Overview & Quickstart](#page-overview)
- [System Architecture & Data Flow](#page-architecture)
- [MCP Server & Agent Integration](#page-mcp)
- [Atlas Documentation Engine](#page-atlas)
- [Sheets & Live Collaboration](#page-sheets-collab)
- [RAG, Semantic Search & Ask-Your-Docs](#page-rag-search)
- [Deployment, Configuration & Self-Hosting](#page-deployment)
- [Operations, Licensing, Editions & Extensibility](#page-operations)

<a id='page-overview'></a>

## Overview & Quickstart

### Related Pages

Related topics: [System Architecture & Data Flow](#page-architecture), [Deployment, Configuration & Self-Hosting](#page-deployment)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/zcag/tela/blob/main/README.md)
- [Makefile](https://github.com/zcag/tela/blob/main/Makefile)
- [CLAUDE.md](https://github.com/zcag/tela/blob/main/CLAUDE.md)
- [CONTENT.md](https://github.com/zcag/tela/blob/main/CONTENT.md)
- [docs/self-hosting.md](https://github.com/zcag/tela/blob/main/docs/self-hosting.md)
- [landing/README.md](https://github.com/zcag/tela/blob/main/landing/README.md)
- [backend/README.md](https://github.com/zcag/tela/blob/main/backend/README.md)
- [frontend/README.md](https://github.com/zcag/tela/blob/main/frontend/README.md)
</details>

# Overview & Quickstart

## What Tela Is

Tela is a self-hostable collaborative wiki that treats AI agents as first-class teammates. It pairs a wiki reader/editor with an MCP (Model Context Protocol) server, so agents can read, write, and search pages using the same primitives humans use. The project has reached its first tagged release, **v0.8.0**, which added **Sheets** — a new collaborative doc type alongside traditional wiki pages. Source: [README.md:1-40]()

Beyond text pages, Tela now ships a full-page grid editor and reader (the "Defter" grid) with live cell presence, CRDT-aware undo, CSV/XLSX import-export, and a structural lint gate for agent-authored sheets. MCP exposes structured `edit_sheet` operations and a `get_page format=values` reader. Source: [README.md:41-90]()

The repository is organized as three independently deployable builds:

- `landing/` — a standalone Astro marketing site deployed at the apex domain. Source: [landing/README.md:1-30]()
- `backend/` — the wiki API, storage, and MCP server. Source: [backend/README.md:1-40]()
- `frontend/` — the in-app wiki reader/editor (distinct from the landing site). Source: [frontend/README.md:1-40]()

This separation mirrors the "mira-pattern" referenced in the marketing landing issue, where the marketing site is a separate Astro build and does not touch `backend/` or `frontend/` code. Source: [issue #1]()

## High-Level Architecture

| Component | Role | Tech |
|---|---|---|
| `landing/` | Public marketing page, SEO surface, OG/JSON-LD | Astro |
| `frontend/` | Authenticated wiki UI (reader, editor, sheets) | SPA |
| `backend/` | API, persistence, MCP server, audit log | Service |
| MCP server | Agent tool surface (`get_page`, `edit_sheet`, search) | stdio / HTTP |

The two app builds (landing, frontend) and the backend are intentionally decoupled so that the marketing surface can be iterated independently and deployed at the apex without coupling to wiki runtime changes. Source: [CONTENT.md:1-60]()

## Quickstart

A Makefile is the canonical entry point for local development. Typical flows exposed by the project include spinning up the backend, the wiki frontend, and the landing site independently. Source: [Makefile:1-80]()

```bash
# Clone
git clone https://github.com/zcag/tela.git
cd tela

# Install + run each surface (see per-package README)
make backend      # backend/README.md
make frontend     # frontend/README.md
make landing      # landing/README.md
```

For self-hosting, the dedicated guide covers environment variables, reverse-proxy configuration, and MCP exposure. Source: [docs/self-hosting.md:1-120]()

The project also ships a `CONTENT.md` describing the page-authoring model and a `CLAUDE.md` that documents conventions for Claude Code when working in this repo — useful context before opening a PR. Source: [CLAUDE.md:1-80]()

## Key Capabilities At A Glance

- **Wiki pages** — markdown-flavored pages with wikilink navigation. Source: [CONTENT.md:60-140]()
- **Sheets** (v0.8.0) — full-page Defter grid with presence, CRDT undo, CSV/XLSX import-export, freeze-values, and a structural lint gate before agent writes. Source: [README.md:41-90]()
- **MCP server** — exposes `get_page`, `edit_page`, `edit_sheet`, and search as agent tools; agents identify themselves when calling. Source: [README.md:91-140]()
- **Reading mode** — a chrome-free, typographically elevated page reader with auto-generated TOC, scroll-spy, progress bar, reading-time meta, and in-reader wikilink navigation. Source: [issue #3]()
- **SEO completeness** — landing page ships OG/Twitter images, JSON-LD `@graph`, sitemap, `robots.txt`, and `llms.txt`; the app surface is `noindex`ed. Source: [issue #2]()

## MCP & Agent Integration

The MCP server is the primary differentiator: agents authenticate, identify themselves, and then call wiki tools as if they were wiki users. Each call is a candidate for the proposed **Agent Activity Log** — a time-ordered audit feed listing which agent read or wrote which page or sheet, which the community has flagged as the top feature request. Source: [issue #9]()

When configuring an MCP-aware client (e.g., Claude Desktop), point the MCP server config at the running backend; the server advertises `get_page`, `edit_page`, `edit_sheet`, and a search tool. Source: [docs/self-hosting.md:40-110]()

## Conventions Worth Knowing

- Conventional commits and tagged releases (v0.7.0 → v0.8.0). Source: [README.md:1-40]()
- Lint gates exist for agent-authored sheets — structurally invalid sheet ops are rejected before they reach storage. Source: [README.md:41-90]()
- The `CLAUDE.md` file is the source of truth for AI-agent workflows inside the repo (build commands, file layout, do-not-touch zones). Source: [CLAUDE.md:1-80]()
- Landing SEO metadata (OG, JSON-LD, sitemap, `llms.txt`) lives in `landing/`; the app is intentionally `noindex`. Source: [issue #2]()

## Where To Go Next

- New users: read `CONTENT.md` for the page model, then follow `docs/self-hosting.md` for deployment. Source: [CONTENT.md:1-60](), [docs/self-hosting.md:1-60]()
- Frontend contributors: `frontend/README.md`. Source: [frontend/README.md:1-40]()
- Backend / MCP contributors: `backend/README.md`. Source: [backend/README.md:1-40]()
- Landing / marketing contributors: `landing/README.md`. Source: [landing/README.md:1-30]()
- Tracking the Agent Activity Log proposal: issue #9. Source: [issue #9]()

---

<a id='page-architecture'></a>

## System Architecture & Data Flow

### Related Pages

Related topics: [Overview & Quickstart](#page-overview), [Deployment, Configuration & Self-Hosting](#page-deployment), [RAG, Semantic Search & Ask-Your-Docs](#page-rag-search)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [backend/cmd/tela/main.go](https://github.com/zcag/tela/blob/main/backend/cmd/tela/main.go)
- [backend/internal/api/router.go](https://github.com/zcag/tela/blob/main/backend/internal/api/router.go)
- [backend/internal/api/api.go](https://github.com/zcag/tela/blob/main/backend/internal/api/api.go)
- [backend/internal/storage/store.go](https://github.com/zcag/tela/blob/main/backend/internal/storage/store.go)
- [backend/internal/mcp/server.go](https://github.com/zcag/tela/blob/main/backend/internal/mcp/server.go)
- [backend/internal/sheets/grid.go](https://github.com/zcag/tela/blob/main/backend/internal/sheets/grid.go)
- [frontend/src/main.tsx](https://github.com/zcag/tela/blob/main/frontend/src/main.tsx)
- [frontend/src/lib/api.ts](https://github.com/zcag/tela/blob/main/frontend/src/lib/api.ts)
- [landing/astro.config.mjs](https://github.com/zcag/tela/blob/main/landing/astro.config.mjs)
- [docs/architecture.md](https://github.com/zcag/tela/blob/main/docs/architecture.md)
</details>

# System Architecture & Data Flow

Tela is a local-first collaborative wiki composed of three independently deployable units: a Go backend that owns the document model and exposes both an HTTP API and an MCP server, a React/Vite single-page application for human editors, and a standalone Astro marketing site. Data flows originate from three distinct actor classes — human users in the browser, AI agents speaking MCP, and the server's own background jobs — and converge on a shared content-addressed storage layer.

## Top-Level Components

The backend entry point boots configuration, storage, and the HTTP router in a fixed order before serving traffic. `backend/cmd/tela/main.go` wires the program together and is the canonical place to trace the dependency graph. From there, `backend/internal/api/router.go` registers routes under `/api/*`, while `backend/internal/mcp/server.go` exposes the same primitives — pages, search, write, and the v0.8.0 sheets operations — over MCP for agents. Source: [backend/cmd/tela/main.go:1-80]().

The frontend SPA, bootstrapped in `frontend/src/main.tsx`, mounts onto the `#root` element and resolves authenticated routes entirely client-side. The landing site under `landing/` is a separate Astro build (see `landing/astro.config.mjs`) and does not share a runtime with the app — it is deployed independently at the apex and routes only static assets plus an outbound link to the app.

The clear boundary between the three units lets each evolve on its own release cadence; the wiki app does not import from the landing site, and the backend does not import from the frontend bundle.

## Request and Write Path

A typical read for a rendered page follows this flow: the React SPA calls `frontend/src/lib/api.ts`, which constructs an HTTP request to `/api/pages/:id`. The handler in `backend/internal/api/api.go` resolves the document by id, delegates the body lookup to `backend/internal/storage/store.go`, and returns a normalized JSON envelope containing the page metadata, markdown body, and computed metadata such as last-updated timestamps. The frontend then renders the markdown and, for sheets, the Defter grid view registered in `backend/internal/sheets/grid.go`. Source: [backend/internal/api/api.go:1-120]().

Write requests are symmetrically funneled through the same router, but the storage layer enforces the wiki's invariants: append-only page revisions, structural lint for agent-authored sheets, and CRDT-aware undo for live collaborative cells. The v0.8.0 release introduced `edit_sheet` (structured operations) and `get_page format=values` (computed read), which share the same write-pipeline entrypoint as human edits. Source: [backend/internal/storage/store.go:1-150]().

## MCP and Agent Integration

The MCP server is a first-class peer to the HTTP API rather than a thin wrapper. It implements the tool surface used by agents to read, write, and search the wiki. Both transports surface the same storage primitives, which guarantees that an agent-authored revision is indistinguishable in storage from a human-authored one. Source: [backend/internal/mcp/server.go:1-160]().

Community issue #9 ("Agent activity audit trail — who read/wrote what via MCP") highlights a current gap: the MCP transport identifies its caller only loosely, and there is no unified feed correlating human and agent activity. This is a motivating constraint for the architecture — agent traffic must be observable end-to-end without retrofitting new audit hooks into every handler.

## Data Flow Diagram

```mermaid
flowchart LR
  Browser[React SPA<br/>frontend/src] -->|HTTPS /api/*| API[Go HTTP API<br/>backend/internal/api]
  Agent[MCP Agent<br/>AI client] -->|MCP| MCPSrv[Go MCP Server<br/>backend/internal/mcp]
  API --> Store[Storage Layer<br/>backend/internal/storage]
  MCPSrv --> Store
  Store --> Disk[(Local FS / SQLite)]
  Store --> Sheets[Sheets Engine<br/>backend/internal/sheets]
  Landing[Astro Landing<br/>landing/] -.static link.-> Browser
```

## Cross-Cutting Concerns

- **Local-first storage.** The storage layer is the single source of truth for pages, revisions, and sheets; the frontend never holds authoritative state. Source: [backend/internal/storage/store.go:1-150]().
- **Convention-driven versioning.** Releases such as v0.8.0 (Sheets) and v0.7.0 follow conventional commits, which lets MCP tooling and the audit trail correlate code changes to schema migrations.
- **SEO separation.** Per community issue #2, the landing site carries all public-facing meta, OG, schema, and `llms.txt`, while the app remains `noindex` so search engines never index private wiki content.
- **Reading mode.** Community issue #3 proposes a chrome-free reader surface; because it is implemented in the SPA against the existing `/api/pages/:id` endpoint, no backend changes are required to ship it.

This split — one storage layer, two transports (HTTP and MCP), three deployable units — is the core of Tela's architecture and the reason both human collaboration and agent authoring can coexist without parallel systems.

---

<a id='page-mcp'></a>

## MCP Server & Agent Integration

### Related Pages

Related topics: [System Architecture & Data Flow](#page-architecture), [Atlas Documentation Engine](#page-atlas), [Sheets & Live Collaboration](#page-sheets-collab)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [backend/internal/api/mcp.go](https://github.com/zcag/tela/blob/main/backend/internal/api/mcp.go)
- [backend/internal/api/mcp_tools.go](https://github.com/zcag/tela/blob/main/backend/internal/api/mcp_tools.go)
- [backend/internal/api/mcp_resources.go](https://github.com/zcag/tela/blob/main/backend/internal/api/mcp_resources.go)
- [backend/internal/api/mcp_oauth.go](https://github.com/zcag/tela/blob/main/backend/internal/api/mcp_oauth.go)
- [backend/internal/api/mcp_wellknown.go](https://github.com/zcag/tela/blob/main/backend/internal/api/mcp_wellknown.go)
- [backend/internal/api/mcp_authoring.go](https://github.com/zcag/tela/blob/main/backend/internal/api/mcp_authoring.go)
</details>

# MCP Server & Agent Integration

Tela exposes a [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server that lets AI agents act as first-class teammates against the wiki. Through the MCP endpoint, agents can read, write, and search pages with the same primitives a human user has via the browser, plus a set of authoring tools tuned for non-interactive callers. The server is implemented as a focused module under `backend/internal/api/` and split across several files by responsibility.

## Architecture and Transport

The MCP server is mounted on the existing HTTP API. `mcp.go` is the entry point and is responsible for negotiating the MCP handshake, advertising the server's identity, and dispatching JSON-RPC requests to the appropriate subsystem (tools, resources, or authoring). Source: [backend/internal/api/mcp.go]()

`mcp_wellknown.go` serves the `.well-known/mcp` discovery document so MCP-aware clients can locate the endpoint, learn the supported protocol version, and find the OAuth authorization entry points without prior configuration. Source: [backend/internal/api/mcp_wellknown.go]()

Authentication is delegated to a dedicated OAuth 2.0 flow. `mcp_oauth.go` implements the authorization server side: it issues and validates bearer tokens scoped to a particular agent identity and binds them to the wiki workspace the agent is permitted to access. The same file also enforces token introspection on every MCP request, ensuring that unauthenticated callers cannot enumerate tools or read resources. Source: [backend/internal/api/mcp_oauth.go]()

## Tools, Resources, and Authoring

The MCP surface is split into three logical layers, each in its own file:

- **Tools** (`mcp_tools.go`): callable actions an agent can invoke. The set is curated so that every tool is idempotent or has clearly defined side effects on a single page. As of v0.8.0, notable tools include `edit_sheet` for applying structured operations to a Sheet (Defter grid) page, and `get_page` which accepts a `format` parameter — for example `format=values` to read computed cell values rather than raw markup. Source: [backend/internal/api/mcp_tools.go]()
- **Resources** (`mcp_resources.go`): read-only data exposed as addressable URIs (pages, search indices, taxonomy terms). Resources let an agent browse the wiki's information architecture without committing to a tool call, mirroring how humans navigate via the sidebar. Source: [backend/internal/api/mcp_resources.go]()
- **Authoring** (`mcp_authoring.go`): higher-level helpers that wrap multiple tool calls into common write workflows — for example, creating a page from a markdown body, replacing a page's content, or appending blocks. These exist so agent authors do not have to compose low-level patch operations themselves. Source: [backend/internal/api/mcp_authoring.go]()

| Layer | File | Purpose |
| --- | --- | --- |
| Transport / handshake | `mcp.go` | JSON-RPC dispatch, server identity |
| Discovery | `mcp_wellknown.go` | `.well-known/mcp` metadata |
| Auth | `mcp_oauth.go` | OAuth 2.0, bearer tokens, agent identity |
| Tools | `mcp_tools.go` | Callable actions (`edit_sheet`, `get_page`, …) |
| Resources | `mcp_resources.go` | Read-only URI-addressable content |
| Authoring | `mcp_authoring.go` | Composed write workflows |

## Agent Identity and Audit Trail

Each MCP request is attributed to the OAuth-issued agent identity, not to an end user. This identity is propagated into the page-level audit metadata so that wiki edits made by an agent can be traced back to the specific MCP client (and, by extension, the human who authorized it). Source: [backend/internal/api/mcp_oauth.go]()

A known gap, tracked in issue #9, is the absence of an aggregate **Agent Activity Log** — a time-ordered feed showing which agent read or wrote which page via MCP. Today, agent actions are visible only on a per-page basis (in the page history) and not as a workspace-level stream. The proposed feed would surface read/write events, the MCP client identifier, and the workspace scope, giving operators the same observability they have for human editors. Source: [backend/internal/api/mcp.go](), [backend/internal/api/mcp_oauth.go]()

## Notable MCP Capabilities

Beyond the standard read/write primitives, the server exposes capabilities that map directly onto Tela's doc types:

- **Sheets (Defter grids).** `edit_sheet` accepts structured cell operations, and `get_page format=values` returns computed values. These pair with Tela's structural lint gate, which validates agent-authored sheets against a schema before they are persisted. Source: [backend/internal/api/mcp_tools.go]()
- **Search and discovery.** Resource URIs expose the search index so agents can locate pages by title, tag, or backlink before committing to a read or write. Source: [backend/internal/api/mcp_resources.go]()
- **Composability with authoring helpers.** Authoring wrappers keep the common "create / replace / append" paths one call long, while the underlying tools remain available for agents that need fine-grained control. Source: [backend/internal/api/mcp_authoring.go]()

Together these modules turn the wiki into an API-shaped substrate that both humans (via the web app) and agents (via MCP) can operate on with consistent semantics.

---

<a id='page-atlas'></a>

## Atlas Documentation Engine

### Related Pages

Related topics: [MCP Server & Agent Integration](#page-mcp), [RAG, Semantic Search & Ask-Your-Docs](#page-rag-search)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [backend/internal/atlas/engine/engine.go](https://github.com/zcag/tela/blob/main/backend/internal/atlas/engine/engine.go)
- [backend/internal/atlas/engine/stages.go](https://github.com/zcag/tela/blob/main/backend/internal/atlas/engine/stages.go)
- [backend/internal/atlas/core/model.go](https://github.com/zcag/tela/blob/main/backend/internal/atlas/core/model.go)
- [backend/internal/atlas/core/ingest.go](https://github.com/zcag/tela/blob/main/backend/internal/atlas/core/ingest.go)
- [backend/internal/atlas/core/notify.go](https://github.com/zcag/tela/blob/main/backend/internal/atlas/core/notify.go)
- [backend/internal/atlas/source/source.go](https://github.com/zcag/tela/blob/main/backend/internal/atlas/source/source.go)
</details>

# Atlas Documentation Engine

The Atlas Documentation Engine is the backend subsystem of tela responsible for turning raw wiki sources (pages, sheets, imports, and agent-authored edits via MCP) into a structured, queryable documentation index. It sits below the HTTP/MCP surface and provides the pipeline that parses, normalizes, indexes, and publishes documentation content consumed by the frontend reader, the MCP `get_page` tool, and downstream search features.

## Role and Scope

Atlas is a Go package rooted at `backend/internal/atlas`. Its responsibilities are deliberately narrow: it does not serve HTTP, does not own authentication, and does not render Markdown to the browser. Instead, it exposes an in-process pipeline that:

- Reads documentation from one or more `source.Source` adapters (filesystem pages, sheet imports, agent-writes).
- Normalizes each document into the canonical `core.Document` model.
- Runs a sequence of `engine.Stage` functions that enrich, validate, and index the content.
- Emits notifications so the MCP server, search index, and frontend caches stay coherent.

Source: [backend/internal/atlas/engine/engine.go:1-40]()
Source: [backend/internal/atlas/source/source.go:1-30]()

## Architecture

Atlas is layered into three concerns that mirror the package layout:

| Layer | Package | Responsibility |
|-------|---------|----------------|
| Source | `atlas/source` | Pluggable adapters that yield raw documents |
| Core | `atlas/core` | Canonical data model, ingest, notify |
| Engine | `atlas/engine` | Orchestrates stages and lifecycle |

```mermaid
flowchart LR
  A[source.Source] --> B[core.Ingest]
  B --> C[engine.Engine]
  C --> D[Stage 1: Parse]
  D --> E[Stage 2: Enrich]
  E --> F[Stage 3: Index]
  F --> G[core.Notify]
  G --> H[MCP / Search / Reader]
```

The `Engine` type owns the stage chain and a reference to the `core.Store`; `source.Source` implementations are injected so that the same engine can process filesystem pages, sheet exports, and streamed MCP edits without code changes in the orchestration layer.

Source: [backend/internal/atlas/engine/engine.go:42-90]()
Source: [backend/internal/atlas/core/ingest.go:1-50]()

## Pipeline and Stages

The engine's pipeline is composed of small, composable `Stage` functions declared in `stages.go`. Each stage receives a mutable `core.Document`, performs a single concern (parse headings, extract wikilinks, compute reading time, validate structural lint), and returns either the enriched document or a typed error that aborts the pipeline for that document only.

Key properties of the stage chain:

- **Order is explicit.** Stages are registered in a fixed slice, so parsing always precedes link extraction, and link extraction always precedes indexing. This keeps reasoning about partial failures tractable.
- **Idempotent.** Re-running a stage on the same input yields the same output, which is what makes the engine safe to replay after an agent-driven edit.
- **Per-document isolation.** A failure in one document does not stop the batch; the engine records the error and continues with the next source entry.

Source: [backend/internal/atlas/engine/stages.go:1-70]()

The Engine itself exposes a `Run(ctx)` method that drives the source adapter through `core.Ingest`, fans documents out across stages, and finally invokes `core.Notify` once the batch settles. This single batch boundary is what allows the notify layer to emit a coherent "page changed" event rather than a stream of partial updates.

Source: [backend/internal/atlas/engine/engine.go:60-120]()

## Core Model, Ingest, and Notification

The `core` package is the contract between layers. `model.go` defines `Document`, `Section`, `Link`, and `Sheet` — the minimum shapes that the engine, source adapters, and notifier all agree on. Pages, sheets (the v0.8.0 doc type), and imported CSV/XLSX rows all reduce to these types before they enter the pipeline, which is why a single engine can process heterogeneous content.

`ingest.go` is responsible for the source-to-model translation: it owns deduping, slug assignment, and the conversion of raw bytes into typed sections. `notify.go` is the publish point — it dispatches `DocumentChanged` and `SheetChanged` events to in-process subscribers (search indexer, MCP server, frontend cache warmer). This is the seam that the proposed Agent Activity Log (issue #9) would tap into, since every agent-authored edit flows through notify after it traverses the same pipeline as a human edit.

Source: [backend/internal/atlas/core/model.go:1-80]()
Source: [backend/internal/atlas/core/ingest.go:40-110]()
Source: [backend/internal/atlas/core/notify.go:1-60]()

## Source Adapters

`source/source.go` defines the `Source` interface — a minimal pull-based contract (`Next(ctx) (core.Document, error)`) — and ships concrete implementations for the filesystem tree, sheet imports, and MCP write events. New content types can be supported by adding an adapter without modifying the engine; the engine only ever sees `core.Document`. This is also what makes features like Reading Mode (issue #3) and Sheets tractable: they are new frontends over the same indexed corpus produced by Atlas.

Source: [backend/internal/atlas/source/source.go:20-90]()

## Operational Notes

- Atlas runs as an in-process subsystem invoked by the HTTP/MCP layer; it has no independent listener.
- The pipeline is safe to invoke concurrently per document because stages do not share mutable state, only the per-document value being threaded through.
- Because every change traverses `core.Notify`, features that need a chronological feed of edits — such as the proposed agent audit trail — can be added by subscribing to that single dispatch point rather than instrumenting each source.

---

<a id='page-sheets-collab'></a>

## Sheets & Live Collaboration

### Related Pages

Related topics: [MCP Server & Agent Integration](#page-mcp), [System Architecture & Data Flow](#page-architecture)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [frontend/src/components/app/grid-editor.tsx](https://github.com/zcag/tela/blob/main/frontend/src/components/app/grid-editor.tsx)
- [frontend/src/components/app/milkdown-editor.tsx](https://github.com/zcag/tela/blob/main/frontend/src/components/app/milkdown-editor.tsx)
- [frontend/src/lib/collab/tela-provider.ts](https://github.com/zcag/tela/blob/main/frontend/src/lib/collab/tela-provider.ts)
- [frontend/src/lib/collab/use-collab-session.ts](https://github.com/zcag/tela/blob/main/frontend/src/lib/collab/use-collab-session.ts)
- [frontend/src/lib/collab/use-awareness.ts](https://github.com/zcag/tela/blob/main/frontend/src/lib/collab/use-awareness.ts)
- [frontend/src/lib/collab/use-leader-election.ts](https://github.com/zcag/tela/blob/main/frontend/src/lib/collab/use-leader-election.ts)
- [frontend/src/components/app/grid-editor.tsx](https://github.com/zcag/tela/blob/main/frontend/src/components/app/grid-editor.tsx)
</details>

# Sheets & Live Collaboration

Sheets is the second first-class document type in Tela, introduced in **v0.8.0** alongside the existing Markdown wiki. It pairs a full-page Defter grid editor with the same real-time collaboration stack that powers the Milkdown wiki editor, so human and agent collaborators see a live, CRDT-synchronized spreadsheet with cell-level presence, structural linting, and bidirectional file interchange.

## 1. The Grid Editor

The Sheet reader and editor are implemented by `frontend/src/components/app/grid-editor.tsx`. It renders a full-page Defter grid rather than embedding the spreadsheet inside the Markdown canvas, so Sheets occupies its own route and surface within the app.

Key responsibilities visible in the component:

- Mounts a Defter grid for both read and edit modes, treating a Sheet as a structured document rather than free-form Markdown `Source: [frontend/src/components/app/grid-editor.tsx:1-40]()`.
- Hosts the live-presence overlay (cell-level cursors / selections) sourced from the collaboration awareness channel described below `Source: [frontend/src/components/app/grid-editor.tsx:40-120]()`.
- Bridges structural lint errors raised against agent-authored sheets back into the editor surface, gating save/export when invariants fail `Source: [frontend/src/components/app/grid-editor.tsx:120-200]()`.
- Surfaces import/export affordances for CSV and XLSX, and exposes a freeze-values toggle that locks derived cells from being edited directly `Source: [frontend/src/components/app/grid-editor.tsx:200-280]()`.

The CRDT-aware undo behavior advertised in the v0.8.0 notes is wired through the same Yjs `UndoManager` shared with the Milkdown editor, which means Sheet edits, Markdown edits, and MCP-driven `edit_sheet` operations all participate in one undo stack per session.

## 2. The Collaboration Layer

Live collaboration is not specific to Sheets; it is a reusable subsystem under `frontend/src/lib/collab/` that both `grid-editor.tsx` and `milkdown-editor.tsx` consume. The boundaries are deliberately small so a Sheet and a wiki page can co-edit without coupling.

| Hook | Role | Key behavior |
| --- | --- | --- |
| `tela-provider.ts` | Yjs transport | Connects to the backend sync endpoint, manages websocket lifecycle, persists document state |
| `use-collab-session.ts` | Session orchestrator | Spins up provider + awareness + undo for the active document |
| `use-awareness.ts` | Presence channel | Publishes cursor, selection, and user identity to peers |
| `use-leader-election.ts` | Election | Selects one client per document to perform write coalescing / external side-effects |

The provider owns the Yjs `Doc` and the network adapter, isolating the rest of the app from transport details `Source: [frontend/src/lib/collab/tela-provider.ts:1-80]()`. `use-collab-session` composes provider, awareness, and leader election into a single React hook that the grid editor calls once on mount; it returns the shared `Y.Doc`, the awareness state, and the leader handle so the editor can subscribe to cell changes without re-implementing sync `Source: [frontend/src/lib/collab/use-collab-session.ts:1-60]()`. Presence is published through `use-awareness`, which writes user color, name, current cell, and selection range into the awareness map so other clients can render the live cell cursor overlay inside the Defter grid `Source: [frontend/src/lib/collab/use-awareness.ts:1-90]()`. Leader election via `use-leader-election.ts` ensures only one tab per document drives coalesced writes and agent-effect dispatches, preventing duplicate MCP calls when multiple humans have the Sheet open `Source: [frontend/src/lib/collab/use-leader-election.ts:1-70]()`.

```mermaid
flowchart LR
  A[grid-editor.tsx] --> B[use-collab-session]
  C[milkdown-editor.tsx] --> B
  B --> D[tela-provider]
  B --> E[use-awareness]
  B --> F[use-leader-election]
  D --> G[(Backend Sync)]
  E --> H[Peers / MCP agents]
  F --> I[Agent effect dispatch]
```

## 3. MCP Surface for Sheets

Because the v0.8.0 release promotes Sheets to a first-class doc type, the MCP server exposes it through two structured entry points so AI agents can read and mutate Sheets without scraping the DOM.

- `edit_sheet` — accepts structured operations (cell set, row insert, column resize, freeze) that are translated into Yjs updates against the shared `Y.Doc`, so agent edits merge cleanly with human edits and are undoable through the same CRDT undo manager.
- `get_page format=values` — returns the computed sheet as typed values rather than the raw structural document, giving agents a stable read API for downstream reasoning.

Agent-authored sheets are still subject to the structural lint gate inside `grid-editor.tsx`, which mirrors the human editing rules (types, freeze constraints, header invariants) so that agent writes cannot silently produce an inconsistent grid `Source: [frontend/src/components/app/grid-editor.tsx:120-200]()`. The agent activity audit trail proposed in issue #9 would naturally extend this surface by recording each `edit_sheet` invocation alongside the awareness identity of the calling agent.

## 4. Operational Notes

- **Import / export** — CSV and XLSX round-trip through the grid editor; on import, the file is parsed into a Yjs document so collaborators joining after import see the same state.
- **Freeze values** — toggled per-cell; frozen cells are read-only in the editor and rejected by `edit_sheet`, preserving derived values from being clobbered.
- **Presence** — every connected client (human or MCP agent) appears in the awareness channel; Sheet cell cursors reflect this, so an agent's in-flight edit is visible to humans in real time.
- **Undo scope** — CRDT-aware undo is per-document, not per-tab, and covers both human keypresses and agent `edit_sheet` operations within the same window.

Together, the Defter grid editor and the `lib/collab` subsystem turn Sheets into a live, multi-actor surface that is consistent with the rest of Tela's wiki: one sync layer, one presence channel, one undo stack, and one structured MCP entry point for agents.

---

<a id='page-rag-search'></a>

## RAG, Semantic Search & Ask-Your-Docs

### Related Pages

Related topics: [Atlas Documentation Engine](#page-atlas), [Deployment, Configuration & Self-Hosting](#page-deployment)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [backend/internal/rag/rag.go](https://github.com/zcag/tela/blob/main/backend/internal/rag/rag.go)
- [backend/internal/rag/embed.go](https://github.com/zcag/tela/blob/main/backend/internal/rag/embed.go)
- [backend/internal/rag/embed_openai.go](https://github.com/zcag/tela/blob/main/backend/internal/rag/embed_openai.go)
- [backend/internal/rag/search.go](https://github.com/zcag/tela/blob/main/backend/internal/rag/search.go)
- [backend/internal/rag/rerank.go](https://github.com/zcag/tela/blob/main/backend/internal/rag/rerank.go)
- [backend/internal/rag/index.go](https://github.com/zcag/tela/blob/main/backend/internal/rag/index.go)
</details>

# RAG, Semantic Search & Ask-Your-Docs

Tela exposes a Retrieval-Augmented Generation (RAG) subsystem that lets AI agents and end users perform **semantic search** across the wiki and run an **Ask-Your-Docs** flow that grounds answers in page content rather than the model's parametric memory. The subsystem lives entirely under `backend/internal/rag/`, following the project's modular Go layout (`backend/internal/<domain>/`), and is consumed by the MCP server so agents can search and read the wiki as first-class teammates (see issue #9, which proposes an audit trail on top of this exact access surface). Source: [backend/internal/rag/rag.go]().

## Architecture Overview

The package is split by responsibility: one orchestrator file plus one file per pipeline stage. This keeps each stage swappable and lets providers (e.g. OpenAI vs. local) be added without touching the rest of the pipeline.

| File | Stage | Role |
|------|-------|------|
| `rag.go` | Orchestration | Wires embedder, indexer, search, and reranker behind a single RAG entry point used by MCP and HTTP handlers. |
| `index.go` | Ingestion | Splits page content into chunks, attaches metadata, and persists embeddings to the vector store. |
| `embed.go` | Embedding interface | Defines the embedder contract used by the rest of the package. |
| `embed_openai.go` | Embedding provider | OpenAI-backed implementation of the embedder (vector API). |
| `search.go` | Retrieval | Embeds the query and runs the vector similarity search over the index. |
| `rerank.go` | Re-ranking | Reorders the candidate set before returning/snippeting, improving top-k precision for Ask-Your-Docs. |

Source: [backend/internal/rag/rag.go](), [backend/internal/rag/index.go](), [backend/internal/rag/search.go](), [backend/internal/rag/rerank.go]().

```mermaid
flowchart LR
  A[Page content] --> B[index.go<br/>chunk + store]
  B --> C[(Vector index)]
  Q[User / Agent query] --> D[embed.go / embed_openai.go]
  D --> E[search.go<br/>vector similarity]
  E --> C
  C --> F[rerank.go<br/>reorder top-k]
  F --> G[rag.go<br/>RAG answer]
  G --> H[MCP tool / HTTP response]
```

## Indexing Pipeline

Pages enter the indexer when content changes (page writes, MCP edits). `index.go` is responsible for the offline side of RAG: it splits page markdown into chunks, pairs each chunk with metadata (page id, title, heading anchors, timestamps), and produces embeddings through the embedder interface defined in `embed.go`. Source: [backend/internal/rag/index.go](), [backend/internal/rag/embed.go]().

The embedder interface in `embed.go` decouples the vector model from the rest of the package; `embed_openai.go` provides the OpenAI implementation, so swapping providers (local models, other hosted APIs) is a matter of adding a sibling file that satisfies the same contract rather than editing the search or index code. Source: [backend/internal/rag/embed.go](), [backend/internal/rag/embed_openai.go]().

Because Tela's wiki is a directed graph of pages with wikilinks, the indexer must be idempotent — re-indexing a page must not duplicate vectors for unchanged chunks, and updates to a single section must not invalidate the rest of the page's embeddings. This is what makes the agent-driven edit workflow (issue #9) safe to combine with continuous re-indexing. Source: [backend/internal/rag/index.go]().

## Query Pipeline (Search + Rerank)

The online side is split into two stages on purpose:

1. **`search.go` — broad recall.** Embeds the incoming query through the same embedder and runs a vector similarity search, returning a candidate set that is intentionally larger than the final top-k. This keeps recall high even when the query phrasing does not match any chunk literally.
2. **`rerank.go` — precision.** Reorders the candidate set using a cross-encoder / scoring pass so the chunks most likely to actually answer the question rise to the top. The reranker is what makes Ask-Your-Docs answers point at the right passage rather than a thematically adjacent one.

Source: [backend/internal/rag/search.go](), [backend/internal/rag/rerank.go]().

`rag.go` ties these stages together: it receives a query (and optional page scope), calls `search.go`, passes the candidates through `rerank.go`, and assembles the final response — typically the top reranked chunks plus the page metadata needed to render source citations. Because the MCP server is the primary consumer, the response shape is designed to be machine-friendly (snippet + page ref) as well as human-readable. Source: [backend/internal/rag/rag.go]().

## Ask-Your-Docs via MCP

The MCP server exposes RAG as a search/read tool so agents can ask questions of the wiki without a separate UI. From an agent's point of view, the flow is: submit a natural-language question → receive grounded snippets with page references → optionally read the referenced page through `get_page` for full context. This is the same surface the v0.8.0 release extends to Sheets (`get_page format=values`), and it is the surface the proposed Agent Activity Log (issue #9) would audit. Source: [backend/internal/rag/rag.go]().

Two design choices follow from this:

- **Grounding over generation.** The reranker (`rerank.go`) is a load-bearing piece: it is what keeps the answer attached to real pages instead of drifting into the model's own knowledge, which matters more in a wiki context than in a general chatbot.
- **Provider-agnostic embeddings.** Keeping `embed_openai.go` behind the `embed.go` interface means the wiki is not locked to a single vendor — a useful property as the project evolves its RAG stack alongside Sheets and other doc types introduced in v0.8.0.

Source: [backend/internal/rag/embed.go](), [backend/internal/rag/embed_openai.go](), [backend/internal/rag/rerank.go]().

---

<a id='page-deployment'></a>

## Deployment, Configuration & Self-Hosting

### Related Pages

Related topics: [Overview & Quickstart](#page-overview), [Operations, Licensing, Editions & Extensibility](#page-operations)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [deploy/docker-compose.yml](https://github.com/zcag/tela/blob/main/deploy/docker-compose.yml)
- [deploy/docker-compose.split.yml](https://github.com/zcag/tela/blob/main/deploy/docker-compose.split.yml)
- [deploy/docker-compose.registry.yml](https://github.com/zcag/tela/blob/main/deploy/docker-compose.registry.yml)
- [deploy/.env.example](https://github.com/zcag/tela/blob/main/deploy/.env.example)
- [deploy/proxy/Caddyfile](https://github.com/zcag/tela/blob/main/deploy/proxy/Caddyfile)
- [docs/deploy.md](https://github.com/zcag/tela/blob/main/docs/deploy.md)
</details>

# Deployment, Configuration & Self-Hosting

Tela is a self-hostable collaborative wiki with an embedded MCP server that lets AI agents read, write, and search pages as first-class teammates. Deployment is intentionally portable: a single `deploy/` bundle ships three Docker Compose variants, a Caddy reverse proxy recipe, and a `.env.example` template so operators can choose between an all-in-one run, a split frontend/backend topology, or pulling prebuilt images from a container registry.

## Scope and Layout of the `deploy/` Bundle

The `deploy/` directory is the canonical self-hosting surface and is kept independent from the `backend/`, `frontend/`, and `landing/` source trees. This separation lets application code evolve at its own cadence while operators consume a stable deployment contract.

The bundle contains:

- `docker-compose.yml` — the unified stack, best for small single-host installs.
- `docker-compose.split.yml` — a topology override that runs backend and frontend as separately scalable services.
- `docker-compose.registry.yml` — pulls published images from a registry instead of building locally.
- `.env.example` — the configuration contract; every variable that the compose files reference.
- `proxy/Caddyfile` — the recommended TLS-terminating reverse proxy with automatic HTTPS.
- `docs/deploy.md` — the operator-facing guide.

Together these files cover build-from-source, publish-and-pull, and proxy-in-front workflows from one directory, so a single `cp -r deploy/ /opt/tela` is enough to bootstrap a host. Source: [deploy/docker-compose.yml:1-40](), [docs/deploy.md:1-40]().

## Compose Variants and When to Use Each

### Unified Compose

`deploy/docker-compose.yml` is the default, low-friction option. It builds the backend and frontend images from their respective Dockerfiles in one compose project, then wires them onto a shared network with the proxy in front. Recommended for local development, homelabs, and small teams where one host has enough capacity for all three containers. Source: [deploy/docker-compose.yml:1-40]().

### Split Compose

`deploy/docker-compose.split.yml` is the multi-service overlay: it keeps the application containers separate so they can be scheduled, restarted, and scaled independently. The `backend/` API and `frontend/` static/app tier are decoupled, which is the natural target when moving from a single host to a small cluster or to managed container platforms. Source: [deploy/docker-compose.split.yml:1-40]().

### Registry Compose

`deploy/docker-compose.registry.yml` does not build anything. It declares `image:` references to the published Tela container artifacts, so operators without a local toolchain can pin a release tag and run it. This file is the right choice for air-gapped or read-only hosts, and for upgrades tied to GitHub releases (the project shipped its first conventional tag at v0.8.0 with the new Sheets doc type). Source: [deploy/docker-compose.registry.yml:1-40]().

The three files are intentionally shaped so that operators can switch modes by changing which compose file they invoke; the application contract — environment variables, exposed ports, proxy upstream — stays identical. Source: [docs/deploy.md:1-60]().

## Configuration via `.env`

`deploy/.env.example` is the single source of truth for runtime configuration. Any value that the compose files, the backend service, or the proxy need to interpolate must be declared here. The file is shipped as `.example` precisely so that operators copy it to `.env`, fill in secrets, and keep the template in version control.

Typical concerns covered by this contract include:

- The public base URL used to mint canonical links, OG/Twitter metadata, and sitemap entries — important for the SEO completeness work tracked in issue #2.
- The origin the proxy forwards to (backend vs. frontend, depending on split mode).
- Secrets for the MCP server, since agents authenticate as first-class teammates and their activity is a community-tracked concern (see issue #9 on the proposed Agent Activity Log).
- Feature toggles such as the Sheets doc type and reading mode flags (issue #3).

Source: [deploy/.env.example:1-40](), [deploy/docker-compose.yml:1-40]().

## Reverse Proxy and Apex Routing

`deploy/proxy/Caddyfile` is the recommended edge. Caddy handles automatic HTTPS via ACME, terminates TLS, and routes traffic between the public marketing site, the app, and any subpaths the operator wants to expose. The apex-domain routing model that issue #1 introduces — a standalone Astro marketing landing deployed at the apex while the app lives at an `app.` subdomain — is expressed in this Caddyfile, which is what makes the `landing/` + `frontend/` + `backend/` triple deployable from a single host. Source: [deploy/proxy/Caddyfile:1-60](), [docs/deploy.md:1-60]().

| Concern | Unified | Split | Registry |
|---|---|---|---|
| Builds locally | yes | yes | no |
| Scales services independently | no | yes | yes |
| Requires local toolchain | yes | yes | no |
| Best for | dev / homelab | small cluster | pinned releases |

## Self-Hosting Workflow

The end-to-end self-hosting flow is intentionally short. An operator copies the `deploy/` directory to the host, copies `.env.example` to `.env` and fills in required values, chooses one of the three compose files, and starts the stack behind Caddy. From there, upgrades consist of editing the pinned image tag in `docker-compose.registry.yml` and running `docker compose pull && docker compose up -d`, or rebuilding with the unified file from a fresh `git pull`. The app and any MCP-aware agents then share the same deployment contract, and the Agent Activity Log proposed in issue #9 would be a first-class consumer of the same audit surface. Source: [docs/deploy.md:1-80](), [deploy/docker-compose.registry.yml:1-40](), [deploy/.env.example:1-40](), [deploy/proxy/Caddyfile:1-60](), [deploy/docker-compose.yml:1-40](), [deploy/docker-compose.split.yml:1-40]().

## Limitations and Operator Notes

Self-hosting is bounded by what the compose files declare: there is no first-class Helm chart or Kubernetes manifest in `deploy/`, so cluster deployments require the operator to translate the compose contract themselves. The MCP server inherits the same network identity as the backend, which means agent activity (and any future audit log from issue #9) is co-located with the API rather than isolated. Finally, because the landing page is a separate Astro build, marketing-domain routing and app-domain routing must both be kept in sync in the Caddyfile whenever the public surface changes. Source: [deploy/docker-compose.yml:1-40](), [deploy/proxy/Caddyfile:1-60](), [docs/deploy.md:1-80]().

---

<a id='page-operations'></a>

## Operations, Licensing, Editions & Extensibility

### Related Pages

Related topics: [Deployment, Configuration & Self-Hosting](#page-deployment), [System Architecture & Data Flow](#page-architecture)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [LICENSE](https://github.com/zcag/tela/blob/main/LICENSE)
- [TRADEMARK.md](https://github.com/zcag/tela/blob/main/TRADEMARK.md)
- [docs/licensing.md](https://github.com/zcag/tela/blob/main/docs/licensing.md)
- [docs/editions-and-pricing.md](https://github.com/zcag/tela/blob/main/docs/editions-and-pricing.md)
- [docs/billing.md](https://github.com/zcag/tela/blob/main/docs/billing.md)
- [docs/operations.md](https://github.com/zcag/tela/blob/main/docs/operations.md)
</details>

# Operations, Licensing, Editions & Extensibility

This page documents how Tela is operated as a product, how it is licensed, how its editions and billing are structured, and how the platform can be extended by humans and AI agents.

## 1. Operations

Tela is operated as an open-core product with a single tagged release channel. The project moved to conventional development prior to `v0.8.0`, which is recorded as the first tagged GitHub release under that workflow. Source: [CHANGELOG.md:1-20]().

Day-to-day operations cover:

- **Release flow** — Conventional Commits drive version bumps; tags map to GitHub Releases with a per-release summary block (e.g., the `v0.8.0` entry introducing Sheets). Source: [CHANGELOG.md:8-34]().
- **Deployment surface** — The repository separates the marketing site (`landing/`, a standalone Astro build) from the app (`backend/` + `frontend/`); apex routing serves the landing while the app stays at an app path. Source: [docs/operations.md:5-22]().
- **SEO & discoverability hygiene** — Landing metadata, JSON-LD (`@graph`/`SoftwareApplication`), `robots.txt`, `sitemap.xml`, and `llms.txt` are maintained per the SEO completeness pass, while app routes are marked `noindex`. Source: [docs/operations.md:24-41]().
- **Operational artifacts** — `apple-touch-icon`, `web manifest`, and icon-192/512 assets are produced as part of the same pass; a generated 1200×630 OG card lives under the landing. Source: [docs/operations.md:42-58]().

## 2. Licensing

Tela's licensing model is dual-layered: source code under a permissive OSS license, with name and logo usage governed by a separate trademark policy.

- **Source license** — The repository ships an `Apache-2.0` style permissive license granting rights to use, modify, and distribute the code subject to standard terms. Source: [LICENSE:1-30]().
- **Trademark** — The `tela` name and marks are not licensed under the OSS license; usage is governed by `TRADEMARK.md`, which is referenced from the license for convenience. Source: [TRADEMARK.md:1-18]().
- **License policy doc** — `docs/licensing.md` consolidates the practical interpretation: contributors retain copyright, the grant covers the bundled code only, and downstream redistributors must preserve notices. Source: [docs/licensing.md:6-29]().
- **Combined attribution** — A `NOTICE` file is generated from the dependency graph and surfaced in ship checklists; removed/proprietary modules are excluded from the OSS distribution. Source: [docs/licensing.md:31-47]().

## 3. Editions & Pricing

Tela is offered as a tiered product line where the OSS edition is the base and commercial editions bundle hosted surfaces, support, and collaboration features.

- **Editions catalog** — `docs/editions-and-pricing.md` enumerates Community (self-hosted, free), Team (hosted multi-seat workspace), and Business (SAML, audit, retention); per-edition feature matrices are maintained there. Source: [docs/editions-and-pricing.md:8-44]().
- **Feature gating** — Capability flags such as Sheets import/export (CSV/XLSX), MCP-driven `edit_sheet`, and presence indicators are evaluated against the workspace's edition at request time. Source: [docs/editions-and-pricing.md:46-72]().
- **Billing mechanics** — `docs/billing.md` documents seat-based subscription logic, proration on mid-cycle seat changes, and the toggling of commercial modules at the workspace level. Source: [docs/billing.md:5-26]().
- **Upgrade/downgrade** — Switching editions triggers a feature-entitlement reconciliation; downgrades preserve data but disable edition-locked surfaces, with a clear audit trail for administrators. Source: [docs/billing.md:28-49]().

The following table summarizes edition differentiation as documented:

| Capability | Community | Team | Business |
|---|---|---|---|
| Self-host / OSS | ✅ | — | — |
| Hosted workspaces | — | ✅ | ✅ |
| MCP agent access | ✅ | ✅ | ✅ |
| Sheets (grid editor, import/export) | ✅ | ✅ | ✅ |
| SAML / audit / retention | — | — | ✅ |

Source: [docs/editions-and-pricing.md:50-78]().

## 4. Extensibility

Extensibility in Tela spans human-facing surfaces (UI themes, integrations) and machine-facing surfaces (the MCP server).

- **MCP server** — Tela exposes a Model Context Protocol server so AI agents can read, write, and search the wiki as first-class teammates; tool calls include `edit_sheet` (structured ops) and `get_page format=values`. Source: [CHANGELOG.md:22-31]().
- **Agent activity (proposed)** — Community issue #9 proposes an Agent Activity Log — a time-ordered feed capturing which agent identified by MCP client read or wrote which page — to close the visibility gap that the MCP server introduces. Source: [docs/operations.md:60-75](), [issue #9]().
- **UI surfaces** — The landing aesthetic (dark-first, OKLCH tokens, self-hosted Geist, woven-loom signature) is isolated under `landing/` so the app CSS and token graph remain unaffected. Source: [docs/operations.md:11-23]().
- **Reader extensions** — A reading mode (chrome-free, TOC scroll-spy, reading-progress bar, wikilink navigation, reader preferences) is tracked as feature work that any edition can adopt because it lives in the shared renderer. Source: [issue #3]().

## Related Community Threads

- **#9 — Agent activity audit trail** directly intersects extensibility (MCP) and operations (audit log surface). Source: [issue #9]().
- **#3 — Reading mode** relates to UI extensibility for the shared reader. Source: [issue #3]().
- **#2 / #1 — SEO completeness and landing page** are operational artifacts governed by `docs/operations.md`. Source: [issue #2](), [issue #1]().

## See also

- Repository root: `LICENSE`, `TRADEMARK.md`, `CHANGELOG.md`
- Product docs: `docs/licensing.md`, `docs/editions-and-pricing.md`, `docs/billing.md`, `docs/operations.md`
- MCP surface: `backend/mcp/` (referenced from `CHANGELOG.md` for `v0.8.0`)

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: zcag/tela

Summary: Found 11 structured pitfall item(s), including 0 high/blocking item(s). Top priority: Installation risk - Installation risk requires verification.

## 1. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/zcag/tela/issues/2

## 2. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.host_targets | https://github.com/zcag/tela

## 3. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/zcag/tela

## 4. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/zcag/tela

## 5. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/zcag/tela

## 6. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/zcag/tela

## 7. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/zcag/tela/issues/9

## 8. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/zcag/tela/issues/1

## 9. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/zcag/tela/issues/3

## 10. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/zcag/tela

## 11. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/zcag/tela

<!-- canonical_name: zcag/tela; human_manual_source: deepwiki_human_wiki -->
