CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Overview
Static marketing site for Citrus Dental (a dental clinic in Varthur/Whitefield, Bengaluru), built with VitePress. Content pages are Markdown; interactive bits (signup/booking forms, appointment date-time picker, carousel) are Vue components loaded into the default VitePress theme.
Commands
npm run docs:dev— start local dev servernpm run docs:build— build static site to.vitepress/distnpm run docs:preview— preview the production build locally- No test suite, linter, or CI config exists in this repo.
- Node version is pinned via
.nvmrc(23.5.0).
Architecture
Content = Markdown, interactivity = Vue components. Each top-level .md file (index.md, book.md, register.md, contact.md, faq.md, pricing.md, team.md, services/*.md) is a VitePress page. Pages that need interactivity import components from components/ directly inside a <script setup> block and use them in the page body (see book.md and register.md).
Site config (.vitepress/config.mts) is the source of truth for nav, sidebar, and SEO/social metadata:
servicesarray at the top defines the full service list once, and is reused both for the nav/sidebaritemsand for generating the JSON-LDhasOfferCatalogin the structured-data script — keep new services in sync with actual files underservices/.- A large inline JSON-LD
MedicalClinicschema block carries business info (address, hours, ratings, socials, staff). Update this when real-world business details change (this file has seen several such commits — hours, staff, etc.). transformHeadgenerates per-page canonical URL and OG/Twitter meta frompageData.- GA and Meta Pixel tracking scripts are injected directly in
head. - Theme customization lives in
.vitepress/theme/index.ts(extendsDefaultTheme) and.vitepress/theme/style.css.
Form flow (components/SignupForm.vue) is the shared component behind both book.md (appointment booking) and register.md (patient registration):
- Gates the form behind Google Sign-In (
components/GoogleSignIn.vue, using Google Identity Services and a hardcoded OAuth client ID) — the actual form fields only render afterisSignedInis true. - Collects base fields (name, phone, age, gender) plus an
intentdiscriminator ("appointment"vs"registration") and any extraformDatapassed in via slot/prop from the parent page. - Pages inject page-specific fields (e.g.
TabbedAppointmentPickerinbook.md, area/sourceMultiselects inregister.md) via the default slot, which receivesformDataas a slot prop so extra fields merge into the same submitted object. - Submits via
fetchto${VITE_API_URL}/signup(env var — backend is external/out of repo) withintentdistinguishing appointment vs. registration server-side. - Phone validation is a simple Indian mobile regex (
/^[6-9]\d{9}$/).
components/TabbedAppointmentPicker.vue is a custom modal date+time picker (wraps @vuepic/vue-datepicker for the date tab, hand-rolled 30-min time-slot grid for the time tab), constrained to a 14-day window, Sundays disabled, and slots less than 30 minutes from now disabled. Emits an ISO string via v-model.
components/Carousel.vue wraps vue3-carousel, used for reviews/testimonials elsewhere in the pages.
All Vue components are used via VitePress's Vue-in-Markdown support (<script setup> + component tags directly in .md files) rather than a separate SPA — there is no router or global state store.