A portfolio website for a fictional premium dental clinic (Zapopan, Jalisco, Mexico). Multi-page, built with vanilla HTML/CSS/JS — no frameworks, no build tools.
No installation required. Open index.html in your browser, or serve the folder with any static server (recommended, since the JS uses ES modules):
npx serve .
# or
python3 -m http.server
<script type="module">requireshttp://(notfile://) in some browsers.
- Semantic HTML5
- CSS3 (native custom properties, Grid/Flexbox, no preprocessors)
- Vanilla JavaScript with ES Modules (no bundler)
- Typography: Fraunces (headings) + Inter (body text), via Google Fonts
- Images: real photography supplied by the client, mapped into
assets/images/(services, technology, team, before/after, facilities, testimonials). The patient dashboard's X-rays (patient-portal/) still usepicsum.photosplaceholders since that data is simulated.
smile-studio/
├── index.html, about.html, team.html, technology.html
├── before-after.html, contact.html, faq.html, appointment.html
├── services/ → index + 8 treatment pages
├── blog/ → index + article template
├── patient-portal/ → login.html + dashboard.html (simulated)
├── css/
│ ├── variables.css → design tokens (color, typography, spacing, shadows)
│ ├── base.css → reset + base typography + accessibility
│ ├── layout.css → header, nav, footer, floating buttons, grid
│ ├── components.css → buttons, cards, forms, accordion, modal, CTA banner
│ └── pages/ → page-specific styles
├── js/
│ ├── main.js → entry point, registers all modules
│ ├── modules/ → one module per feature (see below)
│ └── data/ → mock data for the patient portal
└── assets/ → images and icons
| Module | Purpose |
|---|---|
nav.js |
Mobile menu, sticky header, active link |
scroll-reveal.js |
Scroll-triggered animations + animated counters |
gallery-filter.js |
Generic category filter (chips) — used on Before/After and Blog |
before-after-slider.js |
Accessible drag comparator (range input) |
blog-search.js |
Article search by title |
appointment-form.js |
Booking form: time slots, validation, live summary, simulated submission |
contact-form.js |
Contact form validation and simulated submission |
faq-accordion.js |
Accessible accordion (aria-expanded) |
auth-sim.js |
Simulated login/logout via sessionStorage (no backend) |
portal-tabs.js |
Tab navigation for the patient dashboard |
dashboard-render.js |
Renders the patient's mock data into the dashboard |
This is a front-end portfolio project, so there is no server or database:
- The appointment and contact forms validate and show a confirmation, but don't send data anywhere.
- The patient portal uses
sessionStorage: any valid email + a password of 4+ characters "logs in." Patient data (appointments, history, documents) is mock data injs/data/patient-data.js. - There are no real online payments or automated email/WhatsApp reminders.
For production, these would require a real backend (or a service like Firebase) — see "Pending for v2" below.
- Real backend for appointments, authentication, and documents (Firebase or similar).
- Online payment gateway and financing options.
- Automated email/WhatsApp reminders (real API integration).
- Admin panel to manage services, team, blog, and testimonials.
- Internationalization (i18n) for an English version.
- Advanced SEO: Schema Markup for local business, services, and reviews.
- Keyboard navigation and visible focus states on every interactive component.
- ARIA attributes on accordions, mobile menu, and the before/after comparator.
prefers-reduced-motionsupport.- Color contrast checked against the palette defined in
variables.css.