DEV Community

Cover image for I Built an AI Chatbot + Appointment Booking for Primary Care Clinics
Rohit Bhogal
Rohit Bhogal

Posted on • Originally published at rbhogal.com

I Built an AI Chatbot + Appointment Booking for Primary Care Clinics

"So you're a software engineer dipping your toes into AI? Well… you should learn prompt engineering, vector embeddings and databases, RAG, maybe even LangChain..."

Confused Jackie Meme

"Ok... just start with building a chatbot."

So I did. But I didn't want to make just any chatbot, at least have some use in the real world. So I built a simple but useful AI chatbot + appointment scheduler (because why not?) for primary care clinics. No vector databases. No fine-tuning. No LangChain.

Just:

  • Smart GPT prompting
  • Google Calendar API
  • Next.js + Tailwind CSS + shadcn/ui

The Problem

Primary care clinics get bombarded with the same repetitive questions:

  • “Do you accept BlueCross?”
  • “What are your hours?”
  • “Can I get a same-day appointment?”

The Office Stanley eye-roll

Staff are already overworked—and they waste hours every week answering FAQs.


The Idea

Build a lightweight AI assistant that:

  1. Answers patient FAQs automatically using OpenAI ChatGPT
  2. Lets patients book appointments by integrating with the clinic’s EHR (I used Google Calendar API to demonstrate the workflow).

Fast, lightweight, and useful.

I also recently learned Next.js and wanted to get hands-on by building something practical. And while I’m a frontend dev by background, I’m currently diving into Python, Django, and PostgreSQL to level up to full-stack. So this project doubles as a sandbox to experiment and expand my skill set.


Tech Stack

  • Next.js: Frontend + Backend
  • Tailwind CSS + shadcn/ui: UI Components.
  • GPT-4.1 (OpenAI API): Used smart prompting (no fine-tuning or embeddings) to match user questions to pre-defined answers.
  • Google Calendar API: To demo scheduling, so patients can book appointments in available slots.
  • Upstash Redis: Rate limiting (to prevent spamming to OpenAI)
  • Vercel: Deployment.

How the FAQ Chatbot Works

Instead of RAG or vector search, I did this:

  1. I defined a list of common questions + answers.
  2. I asked GPT to match the user’s input to the closest question.
  3. If it found a match, I showed the corresponding answer.

Fast. Cheap-ish. Easy to update.

FAQ system prompt for OpenAI chat completion:

const faqs = [
  {
    question: "Where is your address location?",
    answer: "123 Demo St. AI City MA, 99999",
  },
  {
    question: "What are your hours of operation?",
    answer: "Mon-Friday: 9am - 5pm. Sat-Sun: Closed",
  },
  {
    question: "Is there parking?",
    answer: "Yes there is ample parking available.",
  },
];

export const FaqSystemPrompt = `
You're a helpful assistant. The user might ask frequently asked questions.
Only answer using the FAQs provided below. Just the answer don't pass along "A:". If the user question doesn't match any FAQ, pass the question along. 

Here are the FAQs:
${faqs
  .map((faq, i) => `${i + 1}. Q: ${faq.question}\nA: ${faq.answer}`)
  .join("\n\n")}
`;

Enter fullscreen mode Exit fullscreen mode

Getting the OpenAI API chat completion response inside a POST:

const aiResp = await openai.chat.completions.create({
        model: "gpt-4.1",
        messages: [
          { role: "system", content: FaqSystemPrompt },
          {
            role: "system",
            content: `You are a friendly and helpful medical assistant at a primary care clinic. If a user isn't asking questions relevant to a primary care clinic, don't answer but instead gently remind them to answer questions regarding a primary care clinic. You can reply to general greetings however. Analyze the user's message and determine if they are asking to book an appointment. Reply with 'MED ASSIST BOOK AN APPOINTMENT' otherwise reply normally.`,
          },
          ...chatHistory,
        ],
      });
Enter fullscreen mode Exit fullscreen mode

Code:
FAQs
OpenAI POST


Appointment Booking

The chatbot can also redirect a user to book an appointment through the booking page. This is where I would integrate it using a clinic's EHR's API, but for demo purposes I used the Google Calendar API.

Using the Google Calendar API, I:

  • Pulled busy time slots from a google clinic calendar I set up.
  • Generated available slots in 30-min increments within working hours and converted to PST.
  • Let users pick one from the UI.
  • Booked it directly through the API.

Boom. No phone call needed.

Booking Calendar
Contact Form
Appointment Confirmation

Code:
Booking Calendar
Fetching/Generating Time Slots


Planned Features / Improvements

  • Login using Clerk: User authentication
  • Admin Dashboard: View patients and update incoming appointments
  • Backend Storage: Right now, I’m just using localStorage and it works totally fine for a simple MVP. But I’m planning to switch to Django + PostgreSQL (mostly because I’m learning Python and want the full-stack practice). That said, if you just want to get something working fast, Django is probably overkill. I’d recommend something like Supabase instead: it gives you a hosted Postgres DB and an auto-generated API so it's super quick to set up.

Issues

  • HIPAA Compliance: Although this is a pretty simple and slimmed down application if collecting information other than name, phone number, and email, like reason for visit, HIPAA compliance is required.
  • The calendar selects the current day on initial load, but it should select the first day with available slots.

Lessons Learned

  • You don’t need LangChain or RAG to build something actually useful.
  • Prompt engineering can go a long way with the right constraints.
  • Working with UTC date timestamps sucks.

✍️ Final Thoughts

This isn’t a massive AI system—but it’s a real solution to a real problem.

If you’re a dev looking to break into AI or build something tangible:

  • Start small
  • Use smart prompting
  • Ship it

Would love to hear your thoughts—and if you have ideas to improve it.

Check it out here (I even built a landing page):


🙌 Thanks for reading!

Drop a ❤️ if you found this interesting.
Or share what you've built!

rbhogal.com

Top comments (1)