OdontoX v1.7 Stable — consolidated release notes
Window covered: 2026-04-26 → 2026-05-21 Login tag at the time of writing: v1.10.0 Public name: v1.7 stableWhat is “v1.7 stable”?
The original v1.7 release shipped at the start of May and put a real chat redesign, a fully featured Marketplace, and an overhauled appointment timeline in the product. Everything we have shipped since then — across 25 days, dozens of incremental fixes, and the v1.8 / v1.9 / v1.10 increments — has been about taking those features from “first cut” to “you can run a clinic on this all day, every day, and not notice it.” That is what “v1.7 stable” means here. One paragraph for the headline list: we made the calendar bigger and faster, we automated WhatsApp end-to-end, we shipped a real Marketplace, we tightened up billing and trial emails to actually arrive on the right day, we rebuilt the patient list and Medical Record Numbers, and we cleaned up Settings so you stop scrolling for the toggle you want. We also did a lot of plumbing work under the hood — sessions stop dying mid-shift, database bursts no longer take down sign-in, and the worker is meaningfully cheaper to run. This document is organised by role. Pick the section for the seat you actually sit in.For Clinic Owners & Admins
People running the business — overview, settings, billing, staff, AI insights.Settings is now grouped into 8 labelled sections
The Settings page used to be a 22-card wall. We grouped them under Clinic & branding, People & access, Clinical setup, Scheduling, Documents & finance, Communication, Integrations & devices, and Account / security / audit. Sections collapse automatically when nothing in them applies to your clinic. Less scrolling, no more “where did that toggle go?” hunts. Cards no longer truncate their descriptions either — you can see what is inside before clicking.Per-event, per-audience email opt-in matrix
The old Notifications screen had five global toggles. The new one is a grid: every operational email (appointment created, cancelled, rescheduled, invoice issued, treatment plan accepted, low-stock alert, EOD report, and more) has an independent opt-in for the patient, the assigned doctor, clinic admins, and the broader clinic staff. Defaults are tuned to cut inbox noise — clinic-wide CC on every appointment ping is OFF by default. There is a one-click “silence this whole audience column” button and a one-click “reset row to defaults” button. Mobile view collapses each event into its own card with the same controls. Your existing opt-outs from the old flag-based system were preserved automatically when we shipped the matrix.My Billing tile is back, with Invoices and Receipts tabs
The “My Billing” tile in Settings → for admins was hidden for a while across all clinics due to an over-broad feature gate. It is fully restored. The panel now has separate Invoices and Receipts tabs (unpaid documents on one side, paid documents on the other), each with a count so you can see at a glance whether anything is outstanding. Preview and Download stream the canonical server-rendered PDF — the same byte-identical file the OdontoX billing team sees — instead of a separately-generated client layout that could drift from the official copy. Trial subscriptions are now clearly labelled “Pro Trial” / “Pro+ Trial” with an “ends [date]” subtitle, instead of just showing the plan name with a small badge. Annual price and next-billing rows are suppressed while you are on trial, because neither applies.Bank QR code on every subscription invoice
OdontoX subscription invoices now carry a scan-to-pay QR in the Payment Instructions section. Point your bank’s app at the QR to skip typing IBANs and account numbers. Paid receipts include a “Bank Details” block for future reference. Old invoices regenerate their PDF on download or re-send so the QR appears even on invoices that pre-dated this change. The first time you sign in after your plan activates, a one-time celebratory toast says “Your plan is now active — Welcome to [Plan]!” with a link to your billing tab. It fires once and never again.Trial countdown banner that everyone sees
Every signed-in user at a clinic on trial now sees a persistent trial countdown banner at the top of the app. The colour shifts from neutral to amber at 7 days and to red at 3 days, so the urgency is clear at a glance. Until this shipped, the trial expiry was invisible until the moment we locked the clinic out — receptionists and doctors had no warning at all. Admins have an “Upgrade now” button right on the banner; doctors and receptionists see the banner without the button (filing the request would only be noise for them).Trial / billing email accuracy
We fixed the family of “I got the reminder and the suspension on the same day” / “the trial ended a day early” complaints in one pass. Trial expiry now sends a proper email instead of silently locking the account. A 24-hour grace period kicks in after the deadline before access is locked, giving admins time to renew without an emergency call. Trial and billing end-dates are now stored as 23:59:59 Pakistan time instead of midnight UTC, so a trial promised “ends May 31” actually lasts until the end of May 31 PKT. “Today’s revenue” and “today’s appointments” dashboard cards now use the Pakistan calendar day too. Suspending a clinic now sends the admin a polished email letting them know access has been paused, that nothing has been deleted, and offering a free demo with onboarding and staff training.Module Marketplace at market.odontox.io
OdontoX now has a dedicated Marketplace surface at market.odontox.io with its own polished home page — hero banner, “Recommended for you” carousel based on the modules you already use, and a left rail that filters listings by module or category. Browse and subscribe to DICOM Imaging, WhatsApp API, In-Patient, Insurance, Marketing & Recalls, Medical Record Numbers, extra storage, and portal seats. Each listing carries its own version label and “What’s new” feed (so you can see exactly what changed in DICOM v1.2.0 before you subscribe). The subscription lifecycle is real: submit a request → invoice is issued → once payment lands the app activates and you receive a “live” email with a 3-step quickstart. Settings carries a Marketplace card showing every add-on you are subscribed to plus any in-flight requests. The main app sidebar now carries a Marketplace entry that opens a flyout listing your installed apps with an “Explore more” link straight to market.odontox.io. There is also a My Apps page at/my-apps with Subscribed and Requests tabs.
Website Leads inbox
Submissions from your clinic website now flow straight into OdontoX. Point your existing “Contact Us” / appointment-booking page form at a single OdontoX URL with a token unique to that form, and inquiries land in a new Website Leads inbox in Settings. Each lead carries name, email, phone, optional date of birth, and message, with a one-click “Convert to Patient” action that creates the patient record. Pipeline statuses (new → contacted → converted → archived → spam) let the front desk track which leads still need a callback. Per-form tokens mean a main contact form, an appointment-booking page, and a careers inquiry can each have its own. Allowed-origin lock + per-token rate limits prevent abuse if a token leaks. Auto-reply email can be turned on per form.Doctors and receptionists manage their own signature
Doctors can upload, activate, and delete their own signature directly from Settings → Signatures — they no longer need to ask an admin. Receptionists can also self-manage signatures used on receipts, invoices, and quotations. Receptionist signatures continue to render with the “Receptionist” sub-line and never carry the “Dr.” prefix; that prefix stays reserved for doctors, dentists, and clinic admins.Patient portal seats and storage as a separate concept from records
Patient records and patient logins are now two different things. Every patient you add is a record — unlimited on Pro and Pro+. Provide portal access is a separate checkbox on the patient form that decides whether the patient can also log in at id.odontox.io. Until this shipped, every new patient implicitly consumed a login slot, which conflated cost with usage. Settings → My Billing now shows portal seats used vs your plan limit (100 on Pro, 250 on Pro+) with an MAU stat below it. Storage shows in GB with a progress bar. Storage addons come as four fixed monthly tiers (50 GB, 200 GB, 500 GB, 1 TB) at flat monthly rates, with what’s included spelled out — HIPAA-compliant encryption, daily backups, RBAC, audit log for every file action. Portal seat addons come as 3-packs with a Pro+ discount. Both are requestable directly from the My Billing panel.Plan-based permissions and Pro+ defaults
Staff invited to a Pro+ clinic now automatically receive the correct Pro+ permissions from day one — full inventory management, DICOM bridge access, IPD, insurance billing, and advanced AI for doctors; full inventory write and signature management for receptionists. Staff invited to Pro clinics get the focused Pro set. Admin accounts now have a full permission tree like other roles — you can grant or restrict any individual permission for an admin user instead of giving them blanket access. There is also a per-role permission floor for doctors: plan-granted core clinical permissions (procedures, medications, prescriptions) cannot be revoked by a clinic template or per-user override, so a misconfigured permission template can’t lock a doctor out of the basics.Multi-clinic support: clinic switcher, scoped notifications, per-clinic role
If you work across two or more clinics on OdontoX, a clinic picker now appears at login and a switcher dropdown sits in the dashboard top bar with the current clinic’s name and a building icon. Switching changes the active clinic immediately — every API call sends the new clinic header, branding and modules bootstrap freshly, and the sidebar logo updates. Your per-clinic role is now respected everywhere too: a user who is admin at clinic A and doctor at clinic B now sees doctor permissions and admin-only settings tabs at clinic B, not admin everywhere. Notifications and toasts no longer leak across clinics. Single-clinic users skip the picker entirely. Inviting a user (or patient) who already has an OdontoX account at another clinic now works correctly — they get a new clinic membership added alongside their existing one instead of “email already exists”.AI Daily Brief is wider and grounded
Ruby’s morning brief now covers lab cases (active, overdue, due today, urgent, ready-for-pickup), inventory alerts (out-of-stock, low-stock, expiring, expired), and the full appointment status breakdown — alongside the existing financial and patient-flow context. We also stopped Ruby from fabricating from sparse data: revenue forecasts now skip the LLM and return a clear “needs more data” message when you have fewer than 5 invoices in the relevant window, and the daily brief no longer flags legitimate large CSV imports as “suspicious data anomalies”. The Churn Risk identifier no longer scores patients who have never had an appointment.Mobile telemetry foundation
A behind-the-scenes change: the mobile app now reports a full device fingerprint on every launch (vendor device id, model, OS version, app version, build number). Useful for support — if someone reports an issue from their phone, we can see what they were on without guessing.For Doctors
Clinical workflows — dental chart, treatment plans, prescriptions, appointments from a clinical view.Dental chart is always on, for every clinic
The dental chart is no longer gated by plan. Previously it was only unlocked for Pro-tier clinics, which was the wrong call — visual tooth charting is core to any dental practice. It is now guaranteed to be active for every clinic at every plan, including Basic. Admins on the receptionist side cannot land on the dental chart anywhere — it is correctly hidden from the appointment Clinical tab and server-blocked at the module level, so the receptionist role can’t reach it even via a direct URL.AI clinical notes in the tooth panel
When you open the per-tooth panel in the dental chart, the Notes tab is no longer a plain text area — it is the full AI clinical notes experience: dictate with the microphone, use toolbar chips (Rewrite / Grammar / Shorter / Detailed), then “Structure with AI” to generate a SOAP-formatted clinical note. Notes save directly to the patient’s clinical record. The panel layout is also tighter — buttons, the mic recorder, and the text area all scale properly inside the narrow tooth detail sidebar instead of bursting out of the column.Dental chart auto-saves
Pending edits now persist 1.5 seconds after the last change. The Save button still works for explicit saves, but you won’t lose work by clicking away or closing the tab — abeforeunload prompt fires if there are still unsaved changes. The save status pill next to the button shows “Unsaved changes (auto-save in 1.5s)” → “Saving…” → “Saved 14:32” so you can see exactly where you stand. The chart itself is also noticeably more responsive: each tooth is an isolated memoized component so clicking one tooth doesn’t redraw the other 31, and the per-keystroke dirty-state check that compared the entire chart on every keystroke is gone. Especially noticeable on iPad.
Treatment planning overhaul
Treatment plans now pull procedures directly from your Service Catalog — pick a procedure and the estimated cost fills in from your catalog price. You can attach optional before and after photos (visible in the PDF export and on the public share link). Required fields (Patient, Plan Name, at least one Procedure) show a red asterisk and an inline error if you try to save without them. After saving a new plan, the app takes you straight to the newly created plan instead of leaving you guessing whether it saved. Treatment plans are capped at 15 procedures per plan to keep them manageable. Treatment plan detail now opens in a single tap (the previous two-tap bug was a URL race), and data caches between view switches so the module loads instantly on revisit instead of firing 4 fresh API calls. You can also apply a discount policy directly in the treatment plan builder — pick a policy and the discounted total calculates and saves with the plan, then renders on the PDF.Prescription print on physical letterhead — actually works
The “Print on Physical Letterhead” prescription mode no longer duplicates the digital clinic header and footer on top of your pre-printed paper. The PDF now contains only the medical content (Rx#, patient, medications, diagnosis, signature) with proper top/bottom margins to land in the writable zone of your letterhead. Default safe-zone margins are now 60mm top and 32mm bottom, and the allowed range was widened to 5–120mm top / 5–100mm bottom so clinics with very tall letterhead designs can dial in the right values. Signatures on PDF documents now print as crisp, opaque black instead of a faded grey ghost — the signature compositor re-tints every stroke pixel to pure black at full opacity before embedding, so the signature is always legible regardless of how it was originally drawn. Admin and doctor accounts now consistently appear as “Dr. ” across the app and on every exported document. The redundant “Admin” sub-line under signature blocks is gone (the “Dr.” prefix already says it).Lab cases — full lifecycle visible
Lab cases now show actual lab cases in the appointment right rail, with status, lab name, due date, and tooth number. The “Files from Lab” card on the lab case detail view actually shows files uploaded by the lab via the shared link (this was silently invisible before because the schema column for attachments was missing from the model). The lab tracking dashboard auto-refreshes when the lab updates status via the shared link — no manual refresh needed. Lab image uploads are JPEG / PNG only (no more ZIP / DICOM extraction), max 25 MB each, with multi-file selection. Creating a lab case is now a full-page experience instead of a cramped popup that cut off the calendar. Labs uploading via the shared link will trigger an in-app toast for the clinic (“New lab attachment for [patient]”) and lab-uploaded images surface in the Radiology Workstation too.Radiology workstation — DICOM, X-ray, TIFF, all in one place
The DICOM viewer and X-ray viewer are now both called “Radiology Workstation” — one consistent experience for all imaging files. The files module is renamed “X-Ray & Radiology Files” and groups DICOM, X-rays, and any JPG/PNG/WebP radiographs under a single “Radiology” tab; PDFs and reports move to a “Documents” tab. TIFF and DICOM files are auto-converted to PNG in the background at upload time, so by the time you open Ruby AI the image is ready — and the workstation now renders the PNG preview instead of trying (and failing) to display the raw TIFF. Multi-page TIFFs display with pagination and zoom. If a thumbnail is corrupt from an older conversion, it self-heals by triggering a fresh conversion in the background. Ruby AI now analyses TIFF and DICOM files. The Bridge Inbox shows an amber “Processing…” badge while conversion is in progress and clears automatically when ready.Smart patient picker, everywhere
Every patient dropdown in the app — appointments, dental charting, invoices, prescriptions, treatment plans, lab cases, insurance claims — is now a typeahead picker. Type a name, phone, or patient number; up to 20 matches stream in from the server. Recent picks show when the box is empty. Search is backed by a Postgres GIN trigram index so picking a patient stays instant whether the clinic has 50 or 50,000 records. The X-Ray & Radiology Files module also supports searching for patients who don’t yet have any files (so you can find a patient and upload their first X-ray, instead of seeing a blank list).Doctor schedule, enforced
If you mark yourself off on a given day, bookings for that day are now rejected. Appointments that fall outside your configured working hours are also rejected with a clear message. Previously these rules existed in settings but were never checked at booking time. The calendar day view now matches each doctor’s actual working hours — filter to a doctor and the time grid shrinks to show only that doctor’s shift, instead of 9 empty hours at the top. Doctors who are off today show a clear banner instead of an empty grid.Ruby reports — full analysis, exportable
The “History” tab on the DICOM and X-Ray workstations is now called Reports. Each entry is an expandable card showing the full Ruby analysis — overall impression, all findings with severity and CDT codes, recommended views — instead of just a summary line. An Export Report button appears on both the current result and saved reports; clicking opens a print-ready clinical report with the radiograph image embedded so you can print or save to PDF directly from the browser. Reports are saved to the patient record (which is what the success toast now confirms, so you know it’s there without checking the AI Reports tab). The exported PDF has been completely redesigned with your clinic logo, name, address, and phone at the top.For Receptionists
Front-desk — calendar, scheduling, patient intake, billing, follow-ups.Calendar — a top-to-bottom overhaul
We did a lot of work on the calendar this cycle. The headline:- Wider canvas by default. The right-side Overview panel (Status Overview, Doctors Today) starts collapsed so the calendar gets the full canvas right out of the gate. The sidebar is narrower too (320px → 280px). Your choice of “panel open” or “panel closed” is remembered per user.
- Tappable empty slots are off — bookings go through the New Appointment button. Clicking an empty time slot no longer opens a booking form. The calendar is read-only for empty space; day and week views only respond to clicking an existing appointment card. This is a clinic-policy choice — turn click-to-book back on from Settings → Appointment Setup if you want the old behaviour.
- 30-minute default with sensible options. The duration picker now shows just
30 min (default),1 hour, andCustom…(5–480 min for the rare edge case). Tapping a slot stages a 30-minute appointment by default — no more 60-minute placeholder you had to shorten. - Drag-to-reschedule snaps to 30-minute boundaries (
:00or:30), matching the standardised half-hour-slot policy. There is an Appointment Setup toggle to use 15-minute snap if you prefer. - Cancelled and no-show appointments can be rescheduled. Reschedule was previously greyed out for these states because the original slot was in the past. That guard skips for cancelled and no-show specifically — those are exactly the cases where you need to move the patient to a new slot. Rescheduling automatically resets the status to “Scheduled” so the new slot starts clean.
- Per-clinic 12h / 24h time format. A Time Format setting under Appointment Setup lets each clinic choose between 24-hour (13:00) and 12-hour (1:00 PM). It applies everywhere — timeline axis, appointment cards, hover details, drag-to-reschedule confirmations. No more mixed clocks (axis in 12-hour, cards in 24-hour) that made the day view confusing.
- Day view is meaningfully more spacious. Hour rows are now 96px tall, half-hour gridlines mark the
:30mark, a floating “Now” pill in the top-right jumps the view to current time, and each card shows its duration as a tiny pill at the bottom right (30m,1h,1h 30m). Empty days show “No appointments scheduled” instead of a blank grid. Patient names render in Title Case, not SCREAMED IN ALL CAPS. - Week and month views scale to busy clinics. Month view shows a count badge per day, a subtle density tint, and up to 3 compact chips, with a
+N morelink into the full day list. Week view auto-switches to agenda mode when a day has more than 24 appointments — that day’s column becomes a scrollable chronological list of compact chips instead of cards stacking illegibly into lanes. - 15-minute slots in the patient-side reschedule picker. Both the admin reschedule flow and the WhatsApp patient self-reschedule list now offer 15-minute increments instead of only 30-minute marks. Bookings still default to 30-minute appointments.
- Appointment Setup is now its own Settings card. Time Format, Hover time indicator, Allow click-to-book, Default appointment duration, and Drag-to-reschedule snap interval all live in one place.
New Appointment form — actually works on every device
Patient picker, date picker, and time selection all work cleanly inside the booking dialog. Clicking a patient suggestion no longer dismisses the form. The date calendar no longer gets clipped or absorbed by the dialog’s click boundary. The patient search box receives focus automatically when opened so typing immediately filters results. New appointments no longer default to 12:00 AM — the form respects clinic operating hours and snaps to the next available 15-minute slot within working hours. If you haven’t picked patients before, the form shows the 30 most-registered patients as a starting list. Receptionists and admins booking an appointment now correctly leave the Doctor field as “Unassigned” instead of silently pre-filling the logged-in user (which was wrong — receptionists were ending up listed as the treating doctor).Save & Book — book the first appointment when adding a patient
A new “Save & Book Appointment” button on the New Patient form. Staff adding a walk-in or a phone-booked patient can save the record AND open the booking form in one step. Saves a couple of clicks per intake.Editable Medical Record Numbers (MRN)
The Medical Record Number is now editable per-clinic via the existingmrn module. The patient create/edit form surfaces the current patient number as a free-text input; admins can replace the auto-generated value with their own (e.g. DS001, DS0002). Uniqueness within the clinic is enforced. When the MRN module is enabled, the create form shows a clickable hint like “Next: MRN-0201” above the input — one click fills it in. Doesn’t consume the sequence, pure preview. MRN errors now surface as toasts instead of false “Patient updated successfully” — duplicate MRN attempts return a clean 409 with the conflicting number. MRN no longer skips numbers when a save fails (reservation and save now happen in one transaction). Patient list defaults to MRN ascending for MRN-enabled clinics; other clinics default to newest-first.
Patient list — sort, filter, stable pagination
Patient list now has explicit Sort (Date added / Name / MRN) and Status filter (Active / Inactive / All). Sort and filter are persisted per-role so navigating back to the list restores your view. Editing a patient no longer “throws” them to a different page — the list now has a proper ORDER BY (created date desc, id tiebreaker) so pagination is stable across edits. Patient list pagination supports 25 / 50 / 100 per page with previous/next controls and shows the total patient count from the server. Patient profile and patient list show N/A for missing dates of birth instead of incorrectly showing01/01/1970. Date of Birth is now optional when staff add a patient record — useful when a walk-in only provides their name and phone. Patients are still asked for DOB when they sign up via an invite link.
Medical history captured at registration
When staff add a new patient, the form has two tabs — Patient Info and Medical History. The second tab includes blood type, smoking status, alcohol consumption, allergies, medications, past conditions, oral habits, family history, and notes. All fields optional at registration; can be filled in later. Invited patients must complete their medical history before accessing the portal — they see a mandatory form on first login covering the key fields. Oral / dental habits (nail biting, bruxism, mouth breathing, etc.) appear as colour-coded tags in the patient profile and in the Medical Issues panel in the right rail of any appointment.Cancellation reason dialog
Cancelling or marking an appointment no-show now opens a structured dialog. You’re asked why the appointment was cancelled (reason is mandatory), whether the patient was contacted (for no-shows), and whether a follow-up was arranged. All answers save to the appointment record and appear in the History tab so the full audit trail is preserved.Reception AI — actionable Action Items
The receptionist’s main dashboard shows an Action Items panel powered by AI. High-priority tasks (overdue appointments, outstanding balances, unconfirmed bookings, lab cases overdue or coming due, inventory alerts) appear directly on the dashboard with action buttons that deep-link to the relevant record. Overdue invoices are tracked in aging buckets (1-7 days, 8-14 days, 15-21 days, 22+ days), each surfacing as a separate nudge with patient names and PKR totals — older debts get progressively stronger language.Billing tab on every appointment
The Billing tab on the appointment detail page shows three prominent stat cards for Total, Paid, and Balance at the top, with a clean divided breakdown table. Empty state for missing invoices guides reception staff on next steps. Payment validation: entering more than the invoice balance now shows a clear inline error and disables Confirm until corrected, instead of silently capping the amount on blur. Receipts and payment history appear immediately after a payment is recorded. The activity timeline on the invoice refreshes automatically after a payment.Cleaner appointment timeline with Web / WhatsApp tabs
The appointment timeline is now split into Web and WhatsApp tabs. In-app events (status changes, invoices, notes, file uploads) appear under Web; WhatsApp template sends, delivery receipts, and patient replies appear under WhatsApp. The “All” tab merges everything chronologically. Every event shows full date and time in Pakistan time (e.g. “May 18, 2026, 02:08 PM PKT”) instead of vague “X minutes ago” labels.Save and Book + duplicate-appointment block
A patient (or staff) can no longer create a second active appointment with the same patient + date + start time — the server returns a clear 409 with a friendly message. Cancelled and no-show slots are excluded so re-booking after a cancellation still works. Out-of-hours errors now explain why: the message includes the appointment’s start, computed end (start + duration), and the clinic’s open–close window.For Patients & Portal users
Patient-facing — portal, appointments, messages, bills, WhatsApp.Patients can confirm or cancel from email — no login needed
Scheduled appointment emails now show a “Confirm Appointment” button and a “Cancel this appointment” link. Clicking either opens a simple page on the patient portal that records the response and notifies your reception team instantly. No login, no password, no app install.WhatsApp reschedule — even for cancelled / no-show patients
Patients who cancelled or no-showed can now reschedule via WhatsApp. When they reply “reschedule”, the bot picks up the most recent cancelled or no-show appointment as a fallback if no upcoming visit exists. Picking a new slot revives the appointment to “Scheduled” automatically. Available slots in the reschedule list always reflect the clinic’s actual operating hours and the doctor’s schedule — not generic 9 AM / 9:30 AM / 10 AM defaults.Inbound WhatsApp media renders properly
Photos appear inline as full-bleed thumbnails you can click to open at full size. GIFs and short videos play inline with native controls. Voice notes show an in-bubble pill player. Stickers float bubble-less the way they do in WhatsApp itself. PDFs and documents show as a downloadable file chip with the original filename. Previously every inbound image, sticker, voice note, GIF, or document arrived as a plain text placeholder like[Image] or [sticker message].
Real WhatsApp delivery and read receipts
Outbound messages now show the familiarsent ✓ → delivered ✓✓ → read ✓✓ (blue) ticks. When a staff member opens a conversation, the unread inbound messages are reported back to Meta as “read” so the patient sees double-blue on their phone. WhatsApp markdown rendering also works now — *bold*, _italic_, ~strike~, and ```code``` render properly in the chat thread, with URL autolinking and XSS sanitization.
WhatsApp lifecycle automation
WhatsApp messages now fire automatically on key appointment actions — Confirm, Cancel, No-Show, Reschedule, new booking request, new manually-scheduled appointment, completed visit (with optional post-visit Google Review survey one day later). The system fills patient name, date, doctor, and clinic from the appointment, no manual copy-paste. Templates auto-bind to the right trigger event the first time they fire — no more “No WhatsApp automation bound for this event” gatekeepers. Duplicate sends on appointment create and reschedule have been removed (the legacy direct-send code paths used to run alongside the lifecycle dispatcher, so admins could receive the same template twice). A daily reconcile against Meta auto-disables automations whose template was deleted or renamed and syncs language codes when they change.Global WhatsApp notifications + connection awareness
WhatsApp notifications now reach you anywhere in the app — switch to Patients or Appointments and you’ll still get the chime, OS banner, and in-app toast for any new inbound, with an “Open” button on the toast that jumps straight to the conversation. The inbox row of whoever just messaged lights up with a soft emerald-to-indigo gradient pulse until you actually open the thread. The chat thread always opens at the latest message and auto-scrolls when a new message arrives if you’re already at the bottom. A “N new messages” pill appears when you scrolled up to read history. A sticky “You’re offline” banner shows when the tab loses connectivity, and a brief “Back online” confirmation when it reconnects, so you know not to trust your last click during a wifi drop.Patient portal — My Appointments with a Requested tab
The patient portal’s My Appointments now has a Requested tab alongside Upcoming and Past. Pending requests no longer mix with confirmed bookings — patients can see at a glance what’s still waiting on the clinic to confirm. Patient portal Quotations show the linked invoice when a quote has been accepted (”→ Invoice #ODX-…”), and the Invoices list shows where each invoice came from when generated from a quote (”← from Quote #…”). Patient invoice PDFs include a “Generated from Quotation #X” line under the totals.Patient portal billing — Payments & Invoices polish
View / Download buttons on every invoice, receipt, and quotation row now show a per-row spinner and disable while the PDF is being prepared. Clicks during the wait are ignored. The resulting PDF opens in a new tab and is cleaned up after a minute (was leaking forever before). Toast messages are user-friendly, never raw error text.Patient phone is private on customer-facing documents
The Bill To / Received From block on invoices, quotations, and receipts (both the inline document and the PDF) now shows only the patient name and email. The patient already knows their own phone number — printing it on a document the clinic shares with third parties is unnecessary exposure. Public shared-link responses no longer return patient phone at all.Pakistan phone normalisation, everywhere
Every phone field across the app shows a fixed +92 country prefix with a 10-digit entry field. Users can no longer type non-numeric characters or enter more than 10 digits. This eliminates incorrectly-formatted phone numbers being saved and ensures every stored number is consistently in E.164 Pakistan format. CSV-imported phones are normalised to the same format on import.Gender field is Male / Female only
The “Other” and “Prefer not to say” options have been removed from all patient forms and the database.Across the whole product — reliability, speed, and quiet plumbing
These items don’t belong to a single role; they make the product better for everyone.Sign-in and protected pages survive database edge bursts
Our database provider’s edge occasionally blocks a Cloudflare colo for short bursts. The Worker now retries 5 times with exponential backoff (120ms → 3s) on these transients, so login, passkey sign-in, notifications, appointments — everything authenticated — no longer 500s during the burst. The login page also stopped firing a “warm-up” passkey-options request on every mount, which had been doubling the load on the auth route during exactly the worst windows.Sessions stop dying
A handful of session-related papercuts are gone. Flaky wifi reconnect no longer logs you out: multiple in-flight requests racing the same refresh token used to be flagged as a “stolen token replay” and revoke the whole session — the server now recognises a real reuse vs. a 30-second-window race, and the browser uses a cross-tab lock so only one tab refreshes at a time. Multiple browser tabs no longer kick each other out. Sessions also stop dying on every deploy: Cloudflare Workers used to read a stale last-activity timestamp from the database after each deployment and incorrectly time sessions out — fixed. App reload after a deployment no longer redirects to login (a session-storage bridge handles the gap). Logged-in sessions now last approximately 3 months end-to-end; you stay signed in for the full window.Calendar / chat / lab — real-time updates
The lab tracking dashboard auto-refreshes when a lab updates a case status via a shared link. The appointment activity timeline auto-refreshes on shared-link uploads. The Bridge Inbox shows uploaded files instantly (was a 15-second polling cycle before). The clinic SSE event bus moved from HTTP polling to WebSocket push — meaningfully fewer round-trips, real-time delivery.Faster login, faster dashboard, faster everything
The 4–5 second blank screen after signing in is gone — the app reads your clinic from your session token instead of making a separate network call. The dashboard cold-load is ~320KB (down from ~3.5MB) because every module is now lazy-loaded; modules cache for the session after first open. Module navigation feels instant on repeat visits thanks to a 90-second SWR cache. The patient list page no longer freezes for clinics with 5,000+ patients — single-query aggregation replaces what was previously N+1 per-patient fetches.Double-submit guards everywhere
Rapid double-clicks no longer create duplicate records. Create Invoice, Save Quotation, Confirm Payment, appointment booking, status changes, patient creation, lab case creation, lab share-link, prescription save, insurance claim save, and inventory item add/edit all have synchronous double-submit guards that short-circuit the second click instead of waiting for React to re-render the disabled state.Per-clinic safety caps on invoice and quotation amounts
Settings → Documentation has a new “Document Amount Limits” card where admins set a max invoice total and max quotation total. Anything above the cap is rejected with a friendly message before reaching the database. Numeric overflow typos (110000000) no longer leak raw SQL into error toasts — the server returns “The amount you entered is too large…” instead.
Bridge desktop app — Windows-native polish (v1.1.0)
The Bridge desktop app was renamed simply to Bridge everywhere it’s visible — installer title, Start Menu shortcut, taskbar label, system-tray tooltip, Setup window title. Bridge now starts automatically when Windows boots by default, launching minimised to the system tray so it’s already watching the X-Ray folder before staff log in. A “Start with Windows” toggle in the tray menu controls this per user. Tray icon and taskbar icon are correctly rendered on Windows. WebP files captured by Bridge are now recognised and uploaded alongside JPEG, PNG, and TIFF. TIFF retry now works — failed files re-queue and retry on the next drop instead of being silently skipped because of a dedup check.Maintenance mode — properly engineered
Engaging maintenance from Platform Settings now emails clinic staff (admin, doctor, receptionist) — patients are never emailed because the maintenance page tells them. Three actions: Save & engage takes the platform down now, Schedule + announce sets a future window and emails everyone the schedule, Save only tweaks the message text mid-window without spamming. Scheduled maintenance auto-engages and auto-releases — you don’t have to be online when it happens. The maintenance page shows the actual message you set, plus a banner line and the start/end times. Already-logged-in users hitting the gate are correctly redirected (before, only the login page caught it). A 5-minute same-kind dedup guard prevents accidental double-sends.Cut database compute hours and network egress
A meaningful chunk of work happened under the covers to make the worker cheaper to run — notification SSE poll cadence relaxed from 5s to 30s and narrowed to only the columns the toast renders, hourly appointment-reminders cron batches dedup lookups into a single query, the Pool driver opens lazily so ticks with no work due don’t open a Pool at all, the Bridge Inbox polling timer was removed entirely (the WebSocket event bus already invalidates the query on file events), and several wideSELECT * queries on patients were narrowed at hot paths. Net effect: meaningfully lower database compute hours and egress at no cost to user experience.
Per-tab toggles for the WhatsApp module
Admins can independently enable / disable the Inbox, Templates, Automations, Quick replies, Analytics, and Events tabs inside the WhatsApp module — useful when you want specific roles to see only the parts they need.Marketing site performance
The marketing site (odontox.io) is meaningfully faster — HSTS, preconnect to API and asset CDN, Poppins fonts preloaded above-the-fold, critical styles inlined into the HTML before JavaScript loads, GTM and Sentry deferred until after the page is interactive, the 11 MB unusedruby.png deleted, the Bridge demo video lazy-loaded via IntersectionObserver. Page transfer weight reduced from ~18 MB to ~6.6 MB on the landing page.
Login version tag
You’ll see v1.10.0 under the sign-in form. That is the internal version label for the latest entry in this stable series. The stable name shipping with this consolidated set is v1.7 stable.If you spot something that does not match what you’re seeing in the app, or you’d like to walk through any of these features in detail, write to us at [email protected] or book a demo from the link in your account.

