Developer overview
How Mojar fits together: the web app, the RAG API, and supporting services.
Mojar is a multi-service platform. This page maps the system for engineers so you know where to look when you need to integrate, extend, or debug.
Services at a glance
mojar.ai
Next.js 14 web application — chat UI, agent management, embed widget, and API routes for the embed session and token lifecycle.
RAG-API
NestJS application that owns document ingestion, embedding, retrieval, and context assembly. Backed by a Python FastAPI service for ML workloads.
Supabase
Shared Postgres database, auth, and file storage. Both mojar.ai and RAG-API connect to the same Supabase project.
What runs where
| Service | Technology | Role |
|---|---|---|
| Web app | Next.js, AI SDK, Supabase Auth | Chat interface, agent configuration, embed widget host |
| RAG API — NestJS | NestJS, BullMQ, Redis | Ingestion orchestration, embedding coordination, retrieval pipeline, HTTP API |
| RAG API — Python | FastAPI, HuggingFace | ML embedding models, chunk processing |
| Document parser | Apache Tika (containerised) | Extracts plain text from uploaded files (PDF, DOCX, etc.) |
| File-import companion | Uppy Companion | Proxies cloud storage imports (Google Drive, Dropbox, OneDrive, Box) from the browser |
| Queue / worker | BullMQ + Redis | Async job queues for document embedding and housekeeping tasks |
| Database | Supabase (Postgres + pgvector) | Stores agents, documents, chunks, embeddings, and chat history |
End-to-end RAG flow
When a user uploads a document and then sends a chat message, the platform executes this pipeline:
Ingest
documents record is created with status processing.Process and embed
chunks table.chunks table (Postgres pgvector column). The document status advances to completed.Retrieve and answer
When the user sends a chat message, the web app calls the RAG-API retrieval endpoint with the agent ID and the user query.
The RAG service runs a similarity search (cosine distance via pgvector) against the agent's chunks, then optionally re-ranks results for relevance. Adjacent chunks are "sibling-dragged" — the chunks immediately before and after each matched chunk are fetched and merged so the LLM receives full context windows rather than isolated fragments.
Key concepts for integrators
Agents are the central object. Each agent has its own knowledge base (a set of documents), an LLM configuration, and optionally a set of allowed embed domains. An agent is identified by its UUID.
Domains gate the embed widget. Before a widget on an external site can open a session, the calling origin must be registered as an allowed domain for that agent. Each allowed domain has its own domainUuid which is required alongside agentUuid in the loader script.
Session tokens are short-lived JWTs (25-minute lifetime) issued by POST /api/embed/initiate-session. The loader script handles token acquisition and silent refresh automatically.