Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/arrozet/caret/llms.txt

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

Caret is built as a collection of focused microservices that each own a single concern. The React frontend talks to a central Express API Gateway for all HTTP traffic, while real-time collaborative editing bypasses the gateway entirely and connects directly to the Y.js collaboration service via WebSocket. Every service — including the frontend for auth — ultimately talks to the same Supabase Cloud PostgreSQL instance, which acts as the shared persistence layer and identity provider.

System Diagram

The diagram below shows how the five backend services are wired together and which protocols each connection uses.
Frontend (React/Tiptap)
  | REST/SSE via /api/v1
  v
API Gateway (Express, port 3000)
  | /api/v1/auth       -> auth-service     (port 3001)
  | /api/v1/documents  -> document-service (port 3002)
  | /api/v1/workspaces -> document-service (port 3002)
  | /api/v1/folders    -> document-service (port 3002)
  | /api/v1/ai         -> ai-service       (port 8000)

Frontend collaboration WebSocket
  -> collab-service /document/{doc_id}?token={jwt} (port 3003)

All services
  -> Supabase Cloud PostgreSQL / Auth / pgvector
The collab-service is the only service that is not behind the API Gateway. The frontend opens a direct WebSocket connection to it (local ws://localhost:3003 or production wss://ws.caret.page) and authenticates using a Supabase JWT passed as a query parameter.

Protocol Summary

ProtocolPathNotes
REST JSON/api/v1/...Stateless CRUD for documents, workspaces, folders, and auth; routed through the API Gateway
SSEPOST /api/v1/ai/conversations/{conversation_id}/streamAI token streaming; gateway proxies to ai-service on port 8000
WebSocket/document/{doc_id}?token={jwt}Y.js sync (type 0) and awareness (type 1) messages; direct connection to collab-service on port 3003

Key Design Decisions

Collaboration bypasses the gateway

Y.js WebSocket traffic connects directly to the collab-service. Proxying WebSocket frames through the Express API Gateway would add unnecessary latency and complicate connection lifecycle management.

Supabase JS is auth-only on the frontend

The frontend uses the Supabase JS client exclusively for sign-in, sign-out, and reading or upserting user_profiles. All other data access goes through the REST API so the backend controls authorization logic.

AI changes flow through Tiptap

The AI service streams text tokens to the frontend over SSE. The frontend applies suggestions through Tiptap editor transactions, which then propagate through Y.js to all collaborators. The AI service never writes directly to document content tables.

Single PostgreSQL instance

Supabase Cloud PostgreSQL is the only database. It is not hosted on the Hetzner VPS. All services connect to it with service-role credentials; RLS enforces data isolation at the database level.

Production Domains

DomainPurpose
caret.pageReact frontend
api.caret.pageAPI Gateway (REST + SSE)
ws.caret.pagecollab-service (WebSocket)
ops.caret.pageCoolify operations dashboard

Further Reading

Services

Detailed breakdown of each backend service, its stack, responsibilities, and layer conventions.

Database

Full table inventory, pgvector RAG setup, RLS policies, and Y.js persistence tables.

Auth & Security

Supabase Auth identity flow, JWT validation per service, and RLS enforcement.

Build docs developers (and LLMs) love