Skip to content

Architecture Overview

Loquent is a fullstack Rust application built with Dioxus 0.7 (SSR + WASM) and Axum as the HTTP server. It compiles two targets from a single codebase: a native server binary and a WASM client bundle.

main.rs
→ Load .env (dotenv)
→ Start cron scheduler (AsyncCron, Eastern timezone)
→ Register background jobs (report + todo jobs)
→ Build Dioxus router (serves pages + server functions + WASM)
→ Append custom Axum routes (Twilio WebSocket, webhooks, recordings)
→ Bind 0.0.0.0:8080, start Axum with graceful shutdown (SIGTERM/Ctrl-C)

In dev mode, dx serve manages the server lifecycle with hot reload. In production, the app binds directly via TcpListener.

Loquent handles three types of requests through a single Axum router:

All UI pages are defined in routes.rs using Dioxus routing. Two layout wrappers:

  • PrivateLayout — outer wrapper, handles auth gating
  • AppLayout — inner wrapper, provides the navigation shell
PathView
/login, /signupPublic auth views
/Dashboard
/agents, /agents/create, /agents/:idAgent management
/calls, /calls/:idCall history and details
/phones, /phones/buy, /phones/:idPhone number management
/knowledge, /knowledge/create, /knowledge/:idKnowledge bases
/analyzers, /analyzers/create, /analyzers/:idAnalyzer config
/contacts, /contacts/create, /contacts/:idContact management
/todo-types, /todo-types/create, /todo-types/:idTo-do type config
/todosTo-do list

Server functions are defined with #[get], #[post], #[put], #[delete] macros inside each module’s api/ directory. Dioxus auto-registers them on the router. Examples:

  • GET /api/agentsagent::get_agents_api
  • POST /api/agentsagent::create_agent_api
  • GET /api/calls/:idcall::get_call_details_api

Four routes are appended manually to the Dioxus router for Twilio integration and file serving:

PathMethodHandlerPurpose
/twilio/streamGET (WSS)twilio::twilio_streamReal-time audio WebSocket
/twilio/voicePOSTtwilio::twilio_voiceIncoming call webhook (returns TwiML)
/twilio/recordingPOSTtwilio::twilio_recordingRecording status webhook
/recordings/:call_sidGETcall::serve_recordingServe MP3 recording files
ui → shared → bases → mods

Dependencies flow strictly left to right. No layer imports from a layer to its left.

LayerPathPurposeCompiles To
uisrc/ui/UI primitives (Button, Card, Input, Select, Spinner, etc.)Both
sharedsrc/shared/Cross-cutting types, layouts, context, constantsBoth
basessrc/bases/Infrastructure (DB, auth, config, email, error, jobs)Mostly server
modssrc/mods/Feature modules — each a vertical sliceBoth

Server-only code is gated with #[cfg(not(target_family = "wasm"))] throughout bases and mods.

The codebase compiles to two targets simultaneously:

TargetWhatContains
Native (server)Axum HTTP serverDB queries, auth, Twilio WebSocket, AI sessions, file I/O
WASM (client)Browser bundleUI components, client-side routing, server function stubs

cargo check only verifies the native target. Use dx build for a full check across both.

Two job types are registered at startup via app::app_jobs():

  • Report jobs (mods::report) — scheduled email reports
  • Todo jobs (mods::todo) — scheduled to-do processing

Jobs implement the JobTrait (cron expression + async work function) and run on the AsyncCron scheduler in Eastern timezone.

The core flow from incoming call to post-call automation:

Incoming call (Twilio)
→ /twilio/voice → TwiML: start recording + open WebSocket
→ /twilio/stream (WSS)
→ Resolve phone number → agent → realtime config
→ Open AI session (OpenAI Realtime or Gemini Live)
→ Bidirectional audio streaming
→ Tool execution (knowledge queries, client lookup)
→ Call ends
→ /twilio/recording (async)
→ Download MP3 → Transcribe (GPT-4o) → Save
→ Contact enrichment
→ Analyzer execution
→ To-do extraction
→ Email report