← Back to web work

Web Development · Case Study · 2026

Adams Internal Medicine
Building a Solo Practice Website
from the Ground Up

48 pages, 19 audit lenses, one physician, and a site that scores 96 out of 100 across user experience, legal compliance, mobile performance, accessibility, and clinical credibility.

48Pages
96Final Score
19Audit Lenses
96%Image Compression

Overview

What it means to build a healthcare website correctly.

Most medical practice websites fail in predictable ways. They're template sites with stock photography and generic copy. They don't tell you what insurance they accept, whether they're accepting new patients, or how long you'll wait to hear back after booking. They have no meaningful compliance infrastructure. They look the same on mobile as they look in a PDF export from a CMS. They've never been tested by anyone who uses a screen reader, a keyboard instead of a mouse, or a 4G connection in a parking lot.

Adams Internal Medicine is a solo internal medicine practice opening in Richardson, Texas in August 2026. The physician — Dr. Stamatina Adams — is a board-certified internist, University of Patras valedictorian, NIH/NIDDK postdoctoral researcher, and experienced hospitalist with training and practice across Greece, New York, Miami, and Dallas. The challenge was to build a website that represented those credentials honestly, served real patients practically, and held up to the kind of scrutiny a healthcare website should face: legal, clinical, accessibility, and security — not just aesthetic.

The result is 48 pages of original content totaling over 28,000 words, a five-step inline booking system, a 13-question FAQ, ten service landing pages, six patient intake forms, a verified patient review page, a HIPAA Notice of Privacy Practices referencing Texas Chapter 181, and a Content Security Policy with SHA-256 hash verification. It was built and audited iteratively across more than 30 build revisions.


The Brief

A new practice. No existing web presence. Opening August 20, 2026.

The site needed to do everything a practice website does at launch: establish clinical credibility, confirm that the practice is accepting patients, explain what services are offered, name the insurance carriers accepted, provide the address and hours, and offer a way to book. It also needed to do what most practice websites don't: actually answer the questions patients ask, handle the edge cases (prescription refills, post-hospital follow-up, patients transferring care from another physician), and be findable on Google the day DNS was pointed.

The physician's background introduced specific requirements. International training from a Greek medical school needed to be framed as a credential pathway, not an immigration narrative. NIH postdoctoral research at NIDDK needed to be scoped precisely enough that a physician peer could verify it — not vague enough to be dismissed as credential inflation. Three languages needed to be surfaced as a patient access benefit. Community involvement with UNICEF, FLITE to FREEDOM, and the Greek Food Festival needed to appear as a real person, not a PR-polished biography.

And the site needed to open on time — before the practice was live, with a booking system that communicated clearly that appointments were requests subject to office confirmation, not confirmed bookings.

"Every patient has a story. My job is to understand it — and help shape the next chapter."

That quote, from the physician's own biography on the About page, sets the tone for everything the site needed to achieve technically. A patient reading it is evaluating whether this is someone they want to trust with their health. The website's job is to not get in the way of that evaluation — and to answer every practical question before it becomes friction that sends them to a competitor's site.


Architecture

48 pages, zero frameworks, one stylesheet per concern.

The site is a static HTML/CSS/JS build deployed on Netlify. No build step, no framework, no CMS. Every page is a handwritten HTML file. This decision was made deliberately and has specific tradeoffs: the site loads faster than anything generated at runtime, is trivially deployable anywhere that serves static files, has no dependency vulnerabilities, and requires no server-side infrastructure. The tradeoff is that content updates require editing HTML files, which became a known limitation documented in the post-launch punch list.

Technology stack

HTML5 CSS (63 files) Vanilla JS (9 files) Netlify Forms Netlify Headers Schema.org JSON-LD WebP + picture elements PWA manifest Cormorant Garamond + Inter
48
HTML pages
63
CSS files
9
JS files
45
Sitemap entries
36
WebP images
106
Lazy-loaded images
30
Picture elements
6
Patient PDF forms

The CSS architecture is a patch-based system that accumulated across 30+ iterative builds. Each significant change — a mobile layout fix, an accessibility improvement, a new component — landed in its own stylesheet, then linked from all 48 pages. This approach kept individual builds targeted and low-risk (a broken stylesheet can't break an unrelated page), but produced a 63-file cascade that creates a render-blocking waterfall on first load. It's the primary technical debt item carried out of the project, flagged for post-launch consolidation into five logical files.

The nine JavaScript files each serve a specific purpose with no cross-dependencies. smart-back.js is a 282-line custom navigation memory system that records the patient's internal browsing path via sessionStorage, enabling the floating "Back" button on subpages to return to the correct referring page with scroll position restored. booking-widget.js manages the five-step inline booking flow. cookie-consent.js handles the GDPR-pattern consent banner with localStorage persistence. None of the nine files has any external dependency — there is no jQuery, no analytics tag, no chat widget SDK in the build.


Content Strategy

28,000 words written to answer real questions before they become friction.

The content philosophy was simple: every question a patient might have before booking should be answered on the site, in plain language, without requiring a phone call. This produced a site with more content depth than most solo practices build in their first five years — a 13-question FAQ, ten service landing pages, a dedicated page for patients transferring care from another physician, a post-hospital care page for recently discharged patients, a What to Expect page that walks through the visit experience before the patient arrives, and a page explaining the practice's refill and prescription process.

Content decisions that required judgment

GLP-1 medications on the weight loss page. Semaglutide and tirzepatide are the most-searched topic in primary care right now. Patients are specifically asking their internists about them. The weight loss page originally mentioned "medication review" without naming the drug class. A single sentence was added: "Weight-management visits may include discussion of medication options, including GLP-1 receptor agonists, when clinically appropriate." Clinically hedged, patient-facing, and answers the question before it creates friction.
Prescription refill note on the contact page. The most common non-emergency reason a transferred patient contacts a new physician's office before their first visit is to ask about refills. The contact page now has a role="note" block: "Prescriptions and refill requests are handled electronically through the office and sent directly to your pharmacy." It appears in the FAQ as well. Two placements for the one question that would otherwise generate calls.
Booking urgency field. The original booking form offered six reason-for-visit options but no way to communicate urgency. A patient recently discharged from hospital or managing an acute condition has no mechanism to signal that. A "How soon do you need to be seen?" field was added with options including "Recently discharged / needs follow-up soon" — the exact language a post-hospital patient would recognize as describing their situation.
Zocdoc reviews with prior-settings disclosure. The practice was not yet open at launch. The verified Zocdoc reviews — 43 records, 4.95 overall rating — were from Dr. Adams's prior clinical settings. The reviews page states: "Reviews reflect Dr. Adams's verified Zocdoc patient feedback from her prior clinical settings." FTC transparent, clinically honest, and surfaces the reviews rather than omitting them.
International credentials as a credential pathway. Dr. Adams's training at the University of Patras, Greece was a specific narrative challenge — it needed to be framed as a credential pathway comparable to U.S. medical education, not as an immigration story. The credentials page names the specific institution, the valedictorian distinction, the U.S. residency program (St. John's Episcopal Hospital, New York, Class of 2020), the NIH/NIDDK research focus (insulin secretion, pancreatic beta cell biology, metabolic medicine), and the Texas hospital affiliations by name.

The booking flow deserves specific attention as a patient-journey design decision. The original concept was a redirect to an external booking platform. The final implementation is a five-step inline flow: reason for visit, date and time preference, contact information, insurance carrier, and a confirmation review screen. The success state — reached after submission — says exactly what happens next: "Our office will contact you within 1–2 business days by phone or email to confirm your appointment. Please remember that this request does not confirm an appointment automatically." That sentence eliminates the most common source of patient anxiety after submitting a booking form at a new practice that isn't open yet.


Legal & Compliance

HIPAA, THIPAA, FTC, WCAG, and Texas Chapter 181 — all present and correct.

Healthcare website compliance is a category most developers treat as a checkbox. HIPAA Notice of Privacy Practices page: check. Cookie consent: check. Privacy Policy: check. The work done on this site goes meaningfully further than that, because the standards that apply to a Texas medical practice website are more specific than "has a privacy policy."

HIPAA NPP with Texas Chapter 181 citation. The Notice of Privacy Practices is a standalone page, linked from every content page's footer, and explicitly cites Chapter 181 of the Texas Health and Safety Code — the state-level medical privacy statute that provides broader patient protections than federal HIPAA. Most practice websites have a generic HIPAA NPP. This one acknowledges both the federal framework and the state-specific extension.
FTC endorsement transparency on the reviews page. Zocdoc is named as the review source, the verification method is named, and the prior clinical settings context is disclosed. Three things, all required by FTC endorsement guidelines, all present.
Medical disclaimers on all 12 content pages. "This page is for general patient education and service information only. It is not a diagnosis, treatment plan, or substitute for medical advice from a licensed clinician who has evaluated you." Consistent language, present on every service and resource page.
Emergency guidance on the contact page. "If you are experiencing a medical emergency, call 911." The contact form explicitly states it is not for emergencies or urgent medical concerns, and provides the 911 instruction above the form, not buried below it.
Booking form non-confirmation disclaimer. The submission success state makes clear that the appointment is not confirmed until the office contacts the patient. This prevents the implied contract problem that arises when online booking forms create the expectation of a reserved appointment slot.
WCAG 2.1 Level AA conformance target stated. The Accessibility Statement names the conformance level, provides a contact method for patients who encounter accessibility barriers, and was written at the time the accessibility improvements were completed.

Performance

96% image compression. One year asset cache. Zero external scripts.

The single highest-impact performance decision in the project was converting 36 hero images from PNG to WebP using the proper <picture><source type="image/webp"> pattern. The original hero images totalled 53MB. The WebP conversions total 2.2MB — a 96% reduction. The homepage banner image alone went from 3.0MB to 139KB. The <picture> element provides a PNG fallback for browsers that don't support WebP, covering the 3% of users that would need it. All 106 non-LCP images use loading="lazy" and decoding="async".

Asset caching is configured in netlify.toml via Cache-Control: public, max-age=31536000, immutable on the /assets/* path. This means returning visitors never re-download a hero image, CSS file, or font. The PWA manifest and 192px/512px icons allow the site to be installed as a home screen app on iOS and Android.

Zero external JavaScript dependencies.

The site's nine JavaScript files — smart-back.js, booking-widget.js, cookie-consent.js, icon-replacements.js, script.js, local-trust-dismiss.js, billing-page.js, about-credentials.js, and health-conditions-cards.js — are all local. There is no jQuery, no analytics pixel, no chat widget SDK, no third-party tag anywhere in the build.

This has a direct security consequence: the Content Security Policy can set script-src 'self' and actually enforce it. Most sites that add a CSP have to include 'unsafe-inline' because their own inline scripts would break otherwise. This site has no inline scripts (the JSON-LD block is covered by a SHA-256 hash), so the policy is genuinely strict.

The Content Security Policy was delivered via Netlify's _headers file and includes X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, and Permissions-Policy restrictions on camera, microphone, and geolocation. The SHA-256 hash for the JSON-LD Schema.org block was computed and verified mathematically — a confirmed match, not an assumed one. All 69 external links in the site use rel="noopener noreferrer".


Accessibility

Built for the patients who most need healthcare access.

Accessibility in a healthcare context is not a regulatory checkbox. The patients who most need accessible websites are the ones most likely to be using assistive technology: older patients with low vision, patients with motor impairments who use keyboards instead of mice, patients with cognitive disabilities who depend on clear heading structure and predictable navigation. A medical practice website that isn't accessible is a medical practice that's inaccessible to some of the people who need healthcare most.

Skip-to-main-content link on 43 of 48 pages. The five pages without skip links are utility redirects and form success pages. All 43 content pages have a skip link with a visible :focus-visible state using the brand sky blue color.
lang="en" on all 48 pages. VoiceOver and other screen readers use the lang attribute to select the correct pronunciation engine. Without it, English text may be pronounced with incorrect prosody.
FAQ accordion with full ARIA suite. aria-expanded, aria-controls, aria-labelledby, and role="region" are all present and correctly paired on the 13-item FAQ. Each question button announces its state to screen readers.
Contrast ratios verified. The sky blue accent color (#2a739f) achieves 5.18:1 against the off-white background. The olive text (#5d6d48) achieves 5.61:1. Both clear WCAG AA's 4.5:1 threshold for normal text. The homepage banner's white text on the navy gradient overlay was calculated at approximately 10.5:1 — more than double the requirement.
Decorative images have alt="" and aria-hidden="true". The physician portrait has a descriptive alt. All section illustration images are explicitly removed from the accessibility tree.
Cookie consent banner with role="dialog" and aria-live. The banner announces itself to screen readers on appearance and can be dismissed or configured via keyboard.
:focus-visible on all interactive elements. Focus states use the modern :focus-visible selector — visible for keyboard users, invisible for mouse users, consistent with current accessibility guidance.

Mobile Experience

Built for one hand, on a phone, in a parking lot.

The majority of healthcare website traffic comes from mobile devices. A patient who just got a referral, or is standing outside the practice trying to confirm the address, or is in a waiting room filling out paperwork — they're on their phone. The mobile experience received more iterative revision than any other dimension of this build, because it's the experience that matters most.

The tap-to-call button enforces a 48px minimum touch target (WCAG 2.5.5), respects env(safe-area-inset-bottom) so it doesn't overlap the iPhone home indicator, hides when a form input is focused so it doesn't cover the keyboard, and collapses to an icon-plus-label format on screens narrower than 520px. That's four separate mobile considerations, all handled in one component.

The smart back button — which follows the patient as they scroll, positioned just below the fixed header — uses var(--aim-fixed-header-height), a CSS custom property set by JavaScript after measuring the actual rendered header height at runtime. This ensures the button doesn't overlap the header regardless of what the header's pixel height turns out to be on any given device.

The homepage banner, which overlays text on a hero image, required specific mobile treatment. On desktop, the text is position: absolute centered vertically over the image. On mobile, that centering breaks when the image height is constrained — the text falls outside the image or overlaps it incorrectly. The fix kept the text absolutely positioned but switched from vertical centering (top: 50%; translateY(-50%)) to bottom anchoring (inset: auto 22px 34px 22px), and switched the gradient overlay from left-to-right to top-to-bottom so the bottom of the image is dark enough for the text to read against.


Search & Discovery

Day-one indexability and local search presence.

A new practice that isn't findable on Google isn't findable at all. The SEO infrastructure was built to ensure that the moment DNS points to the production domain, the site is ready to be submitted to Search Console and indexed correctly.

Schema.org JSON-LD on the homepage. A @graph block defines three types: MedicalClinic (with address, phone, hours, and areaServed covering Richardson, Plano, Garland, North Dallas, and Dallas County), Physician (Dr. Adams, linked to the clinic via @id), and WebSite. This enables Google's Knowledge Panel, rich snippets in local search, and the information card that appears when someone searches the practice name directly. The inline script is covered by a SHA-256 hash in the CSP — verified mathematically, confirmed match.
Canonical tags on all 48 pages. The site uses ?from= query parameters for internal analytics tracking. Without canonical tags, Google may treat ?from=home and the clean URL as separate pages, diluting indexing authority. Every page now declares its canonical URL explicitly.
45-entry sitemap on the production domain. The sitemap correctly excludes redirect stubs, the 404 page, and utility success pages. robots.txt points to the live sitemap URL at www.adamsinternalmedicine.com.
Unique title and meta description on all 48 pages. No page shares a title or description with another page. The homepage OG tags, Twitter Card tags, and canonical link all point to the production domain — zero test domain leaks.
109 Richardson/North Dallas mentions across site content. Local relevance is a primary signal for Google local search. The site mentions Richardson, North Dallas, Plano, Garland, and Dallas County across pages where the reference is natural — not stuffed.

The netlify.toml configuration includes clean URL redirects for 30+ routes so /about resolves alongside /about.html. A telehealth page that was removed during development is handled with a 301 redirect to the services page — any cached search result or shared link that pointed to that URL lands correctly rather than hitting a 404. The 404 page itself is a custom-designed error page rather than Netlify's default.


Evaluation Methodology

19 lenses. Every stakeholder who will ever read this site.

The site was evaluated iteratively across 19 distinct persona lenses — not as a marketing exercise, but as a systematic way to find the things that conventional QA misses. A security audit catches technical vulnerabilities. A Mom Test catches the things that are technically correct but practically confusing to a 61-year-old in Plano who found the site through a Facebook group recommendation. Both matter.

Three of the 19 lenses were developed specifically for this project and not used in standard web development audits:

Lens Persona Grade Key finding
UserPatient finding a new internist on iPhone at 8:30pmAAll critical info above fold; booking success state sets clear expectations
DoctorSkeptical physician peer reviewing credentialsAABIM named specifically; NIH research scoped to subject area; services stay in lane
LawyerHealthcare attorney doing pre-launch compliance reviewAHIPAA NPP with Texas 181; FTC endorsement disclosure; CSP; booking non-confirmation
MobileiPhone 14, one hand, 5G, parking lotA106 lazy images; tap-to-call with safe-area; smart back button; banner fixed
DesktopReferring physician's office managerA45-page sitemap; clean URL redirects; telehealth 301; zero broken internal links
Disability68-year-old with low vision using VoiceOverB+Contrast verified; FAQ ARIA complete; skip links present; aria-invalid gap in booking
SecurityPenetration tester scanning a healthcare marketing siteB+CSP enforced; zero external scripts; noopener on all 69 external links; X-Frame DENY
StakeholderSilent investor or practice managerAConsistent NAP across all 48 pages; named insurers; professional domain email
Dr. AdamsThe physician reading her own siteABiography sounds like a specific person; community service names real organizations
Mr. AdamsHer spouse deciding whether he's proud of itAShe sounds like herself; shareable; no test artifacts; personal details present
KidsShowing it to a friend on their phoneAValedictorian, NIH, trilingual, scuba diving — specifics kids can relay with pride
Judgey FriendsCompetitive physician colleagues at dinnerB+ABIM named; NIH scoped; no NPI published (intentional decision)
UX/UI ProfGrading it as a capstone projectB+Design system principled; CSS architecture is patch-based (known debt)
Mom61-year-old in Plano from a Facebook recommendationAPhone, address, hours above fold; insurance names carriers she recognizes
Mean BroSkeptical tech-savvy sibling looking for anything to pick atBZero test domain leaks; anchor links resolve; Zocdoc prior-settings disclosed
Fox NewsCable news producer looking for a controversy segmentA+Zero DEI, political, or contested clinical language across all 48 pages
Google NEWThe search crawler on first indexB+Schema.org, canonicals, sitemap — ready; title tag 78 chars (known)
Patient in Crisis NEWRecently diagnosed patient, scared, 6pm ThursdayAPost-hospital, chronic disease, transferring pages all present; urgency field in booking
Five Years Later NEWDeveloper returning in 2031 to update itBDesign system durable; 63-file CSS architecture will age poorly; no CMS

The three new lenses developed for this project — Google, Patient in Crisis, and Five Years Later — each revealed a category of issue that conventional audits don't surface. The Google lens identified the absence of Schema.org structured data, which was added as a pre-launch fix. The Patient in Crisis lens confirmed that the site serves frightened and recently-diagnosed patients adequately through the post-hospital care page, the booking urgency field, and the 911 guidance on the contact page. The Five Years Later lens produced the most actionable long-term punch list: the opening date copy that needs to come down on August 20, the 63-file CSS architecture that will be difficult to maintain without the original developer, and the absence of a CMS that will result in stale content within 12–18 months if not addressed.


Result

96 out of 100. Launch-ready on August 20, 2026.

The site scores 96 across 19 lenses. The four points off are the CSS file consolidation (63 files is functional but architecturally fragile), the homepage title tag truncating at 78 characters in Google search results, the night mode implementation that was built and deferred, and the absence of a CMS for long-term content maintainability. None of these prevent launch. All of them are known and documented.

What the score reflects is a site where every patient-facing interaction works correctly — the booking form sends a request, the FAQ answers the questions patients actually ask, the contact form states response time expectations, the insurance page names the carriers a patient would recognize, and the physician's biography sounds like someone a patient would want to meet. Those are the things that determine whether a website converts a visitor into a booked appointment. Technical correctness is the foundation. Patient trust is what's built on it.

The question this project answers.

What does it actually take to build a medical practice website that serves patients, satisfies lawyers, holds up to physician peer scrutiny, loads fast on a 4G connection, passes accessibility audits, and is ready to be indexed by Google on day one?

It takes 48 pages of original content. It takes a five-step inline booking system with a clear success state. It takes a HIPAA NPP that cites Texas Chapter 181. It takes a CSP with a verified SHA-256 hash. It takes a smart back button whose top position is computed at runtime from the actual rendered header height. It takes 30 build revisions and 19 audit lenses.

And it takes a physician whose biography, written in her own voice, ends with a line that makes a patient want to book an appointment. The website's job is to not get in the way of that.

ADAMS INTERNAL MEDICINE · RICHARDSON TX · WEB DEVELOPMENT CASE STUDY · 2026