A Dental Practice Portal With an AI Receptionist That Books Appointments on the Phone
A multi-clinic dental practice portal. One login gives clinic staff appointments, doctors, patients, call logs and staff access, while Sarah, a self-hosted AI phone receptionist, answers calls and books, reschedules or cancels appointments in the same calendar.
Multi-clinic dental practice
Healthcare · Dental
Product Design, Full-Stack Web Development, AI Voice Agent, Database Engineering & Cloud Deployment
React 19, Node.js, SQL Server, self-hosted LiveKit
Dental clinics run on the appointment book. Every missed call can mean a lost patient, and front desk teams are often helping someone in the chair when the phone rings. The clinic also needed one place to manage doctors' shifts and rooms, treatments, patient history and staff access, so it could stop working across spreadsheets and separate tools.
360Techsys delivered a complete platform in three parts: a React web portal for clinic staff; a Node.js API on Microsoft SQL Server, where every read goes through a view and every write goes through a stored procedure; and an AI voice agent built on a self-hosted LiveKit server. The agent and the portal call the same booking API, so a booking made on the phone appears in the portal calendar straight away, along with a summary of the call.
The AI receptionist taking a booking, the resulting call log, the dashboard, the calendar and the role matrix.
AI receptionist answers inbound calls and books, reschedules or cancels appointments without staff involvement
Agent tools: check_availability, book_appointment, reschedule_appointment, cancel_appointment, transfer_to_staff, end_call
Modules: dashboard, booking, calendar, doctor schedules, patients, visit history, call logs, AI and calendar configuration, user management, settings and support
System roles (Administrator, Senior Dentist, Junior Dentist, Receptionist, Dental Nurse) plus custom roles with per-module view and edit permissions
SQL views and stored procedures: no queries are written directly against the base tables
One agent worker and one API serve every clinic, each with its own prompt, voice, phone number and booking rules
These figures describe the delivered software, not measured clinic outcomes. All portal screenshots use demo clinic data; no real patient information is shown.
Calls to a dental clinic peak at the same times the clinic is busiest: early morning, lunchtime and after school hours. Off-the-shelf booking widgets did not cover phone patients. Hosted voice-AI platforms charged for every minute and left the clinic little control over voice, language or data. Staff also needed different levels of access: a receptionist should not change clinic settings, and a junior dentist needs their own schedule but not the whole practice's records.
The goal was a single platform with three properties. Phone bookings and front-desk bookings had to land in the same calendar, under the same rules. Each staff member should see only the modules their role allows. And the clinic had to own the full stack, including the voice infrastructure.
A voice agent, a staff portal and a locked-down data layer, all sharing one booking API.
The voice agent is written in Python with LiveKit Agents. It uses Deepgram Nova-3 for speech-to-text, Deepgram Aura-2 for natural speech, an OpenRouter LLM (GPT-4o mini by default), Silero voice-activity detection and LiveKit's turn detector, which lets callers interrupt naturally.
Phone numbers connect through LiveKit SIP, so a clinic can bring any carrier's SIP trunk. One worker serves every clinic and loads that clinic's prompt, voice and language for each call. If the backend cannot be reached, the agent falls back to a generic receptionist, so a call is never dropped.
When a call ends, the agent posts the transcript, duration and cost to the portal. The call then appears in Call Logs with a written summary, its purpose and a status of Resolved, Follow-up Needed or No Answer, so the front desk can see which phone conversations still need a person.
Built with React 19, TypeScript and Tailwind CSS v4, the portal gives each role a focused workspace:
Access control works at the level of each module. Every role has a view permission and an edit permission for each module, an authority level, and a permission matrix in User Management that administrators can edit.
New staff receive a temporary password and must change it at first login. Passwords are hashed with bcrypt, and every login is recorded.
Raw SQL is never run against the base tables. The API reads data through 10 SQL views and writes it through 32 stored procedures, with every input parameterised. This hides the internal schema from the application layer and from error messages, and keeps business rules such as booking windows and double-booking checks in one place inside the database. Endpoints used by the voice agent are protected by a shared agent token, and provisioning endpoints by an admin secret.
A GitHub Actions workflow on a self-hosted runner builds the frontend on every push to main and deploys it behind IIS. URL Rewrite sends /api to the Node.js server, so the browser only ever talks to a single origin. PM2 keeps the frontend, the API and the agent running. The LiveKit server and the voice agent run on a Debian VM under Docker and systemd, with Prometheus and Grafana dashboards monitoring the voice infrastructure.
Screens from the DentaClinic portal running with demo data. Select any screen to enlarge it.
Running the voice stack on the clinic's own LiveKit server keeps call data and costs under the clinic's control, and makes it possible to swap the speech or LLM provider later.
Because the agent and the portal call the same booking API, a phone booking and a front-desk booking follow exactly the same availability and booking rules.
Module-level permissions let one portal serve administrators, dentists, receptionists and nurses without exposing data a role should not see.
Keeping all data access in views and stored procedures keeps the schema private and puts validation in one place.
Call summaries and follow-up flags show the front desk which phone conversations still need a person.