Medpro Documentation

01 · Overview

Introduction

Everything you need to know before you open your editor — what’s in the box, what it’s built with, and what it expects from your machine.

Welcome

Thanks for picking up Medpro, a clean, responsive medical & healthcare website template for hospitals, clinics, and healthcare practices. It includes a home page, about, health checkup packages, doctors, departments, and contact pages, plus a 404 page and three template-info pages (style guide, license, changelog) — and every main page ends with an appointment form. This guide walks through installing the template, understanding how the project is organized, customizing content and styling, and shipping it to production. It’s written for developers who are comfortable with the command line but new to this specific codebase — if you already know Astro well, feel free to skip ahead using the sidebar.

All content in the template (names, addresses, phone numbers, testimonials) is placeholder text — replace it with your own before going live.

What’s Included

Source files

The full, uncompiled project source — components, pages, styles, and configuration.

Production build

Not shipped pre-built — the package contains source only. Run npm run build to generate a deployable dist/ folder (see Build & Preview).

Design assets

No Figma or design source files. The project bundles the five Satoshi font weights (public/fonts/), the demo photos, logos, and SVG icons (public/images/), and a favicon.

This documentation

This online guide — the documentation.txt file included alongside the template folder in the download links here.

Features

  • 6 pages (Home, About, Health Checkup, Doctors, Departments, Contact) plus a 404 page and 3 template-info pages (style guide, license, changelog)
  • Astro 7 with static output — no UI framework and no TypeScript required, just .astro components, plain CSS, and vanilla JavaScript
  • Scroll and hover animations with GSAP + ScrollTrigger: a navbar that shrinks on scroll, slide-in reveals, a floating stats card, a services marquee, and mouse-follow parallax — all of which respect prefers-reduced-motion
  • Testimonial carousel built with Swiper, with a YouTube video modal on each slide
  • Accessible, keyboard-navigable tabs for checkup plans and departments, and an off-canvas mobile menu
  • An appointment form on every main page (demo submit handler — see Forms)
  • Responsive at desktop, tablet (≤991px), mobile landscape (≤767px), and mobile (≤479px)
  • SEO meta, canonical URL, Open Graph, and Twitter tags on every page, plus an automatic sitemap via @astrojs/sitemap

Technology Stack

Medpro is a plain Astro project: .astro components, hand-written CSS, and vanilla JavaScript in component <script> tags. There is no React, TypeScript, Tailwind, or Sass.

Astro 7 Vite GSAP + ScrollTrigger Swiper @astrojs/sitemap

Requirements

ToolMinimum versionNotes
Node.js22.12.0 or laterRequired by Astro 7 (set in package.json engines); LTS releases are recommended
Package managernpm 10+ (bundled with Node 22), pnpm, or YarnThe template ships a package-lock.json, so npm is recommended; examples below also cover pnpm and Yarn
Code editor—VS Code with the official Astro extension (recommended by the project’s .vscode/extensions.json) is a comfortable default
Git2.xOnly required if you plan to version-control your customized copy

Browser Support

The built site targets the last two versions of all evergreen browsers:

Chrome Firefox Safari Edge
Internet Explorer

Internet Explorer 11 is not supported. The template ships no polyfills — it relies on modern browser features used by GSAP, Swiper, and its CSS.

02 · Setup

Getting Started

From a downloaded ZIP to a running dev server in five steps.

Installation & Extraction

  1. Download medpro-medical-astro-package.zip from your purchase confirmation email or account downloads page.
  2. Extract it to a folder on your machine — avoid folder names with spaces or special characters. Inside you’ll find the template folder, medpro-medical-astro/, next to a documentation.txt file that links to this guide.
  3. Open the medpro-medical-astro/ folder in your terminal and in your code editor.
bash
# Extract on macOS / Linux
unzip medpro-medical-astro-package.zip
cd medpro-medical-astro-package/medpro-medical-astro

Node.js Setup

Check which version of Node.js is currently active:

bash
node --version
# v22.12.0 or later

If you manage multiple Node versions, tools like nvm or fnm make switching painless:

bash
nvm install 22
nvm use 22

Install Dependencies

From the project root, install packages with your preferred package manager:

npm
npm install
pnpm
pnpm install
yarn
yarn install

This reads package.json and downloads every dependency into a local node_modules/ folder. It only needs to be re-run when dependencies change.

Run the Development Server

npm
npm run dev
pnpm
pnpm dev

This starts Astro’s local dev server (powered by Vite) with hot module reloading — edits to components, pages, and styles appear in the browser immediately without a manual refresh. By default it’s available at http://localhost:4321; the terminal output will confirm the exact address.

Build for Production & Preview

bash
# Compile an optimized production build into dist/
npm run build

# Serve that build locally to sanity-check it
npm run preview

build renders every page to static HTML, bundles and minifies CSS and JavaScript, generates the sitemap, and writes the output to dist/. preview serves that exact output locally so you can verify it before deploying — it does not rebuild automatically, so re-run build after further changes.

Which command do I actually need?

Use dev while you’re customizing the template. Use build, then preview, once before you deploy — it catches issues (like missing imports or a broken component) that the dev server only surfaces when you happen to open the affected page.

03 · Reference

Project Structure

A tour of the folders you’ll actually touch, and the ones you generally shouldn’t.

PathPurpose
public/Files here are copied to the output root untouched — no optimization or hashing. In Medpro this holds every image (public/images/), the Satoshi font files (public/fonts/), and the favicons. See Images & Assets.
src/components/Page sections. Sections used on several pages (TopBar, Navbar, Footer, ContactSection, Testimonials) sit at the top level; sections used by a single page live in a subfolder named after that page (e.g. home/Hero.astro).
src/layouts/BaseLayout.astro defines the common page shell — stylesheet imports, <head> SEO tags, top bar, navbar, and footer — so individual pages only supply their sections.
src/pages/Every file here becomes a route automatically. See Pages for details.
src/scripts/Shared GSAP animation helpers imported by component scripts: reveal.js (slide-in reveals), float.js (floating card bob), and tabs.js (accessible animated tabs).
src/styles/The four global stylesheets imported by BaseLayout, including the theme’s CSS variables in medpro.css. See Styling.
Files not shown above

.vscode/ recommends the official Astro extension and adds a “Development server” launch configuration. .gitignore excludes dist/, .astro/, node_modules/, and .env files. There is no src/assets/, src/data/, or content-collection folder — content is written directly in the components.

04 · Reference

Configuration

The files that control how the project builds, and where to set site-wide values.

package.json

Defines dependencies and the scripts you run from the terminal (dev, build, preview). Add your own script here if you introduce a new tool.

jsonpackage.json
{
  "name": "medpro-medical-astro",
  "type": "module",
  "version": "0.0.1",
  "engines": {
    "node": ">=22.12.0"
  },
  "scripts": {
    "dev": "astro dev",
    "build": "astro build",
    "preview": "astro preview",
    "astro": "astro"
  },
  "dependencies": {
    "@astrojs/sitemap": "^3.7.4",
    "astro": "^7.3.5",
    "gsap": "^3.15.0",
    "swiper": "^14.3.0"
  }
}

astro.config.mjs

Controls integrations, the deployed site URL, and build behavior. Medpro uses a single integration, @astrojs/sitemap, filtered so the template-info pages stay out of the sitemap. Set site to your production domain — canonical URLs, Open Graph image URLs, and the sitemap are all built from it.

javascriptastro.config.mjs
// @ts-check
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

// https://astro.build/config
export default defineConfig({
  // Set this to your production URL (used for canonical links, OG tags and the sitemap).
  site: 'https://example.com',
  integrations: [sitemap({ filter: (page) => !page.includes('/template-info/') })],
});

tsconfig.json

Medpro contains no TypeScript files — this file is Astro’s standard default and only feeds editor tooling (autocomplete and hints in VS Code). It defines no path aliases, so all imports use relative paths such as ../components/Footer.astro.

jsontsconfig.json
{
  "extends": "astro/tsconfigs/strict",
  "include": [".astro/types.d.ts", "**/*"],
  "exclude": ["dist"]
}

Environment Variables (.env)

Medpro doesn’t read any environment variables and needs no .env file to run or build. If you add one later — for example a form endpoint or an API key — create a .env file in the project root for values that differ between environments or shouldn’t be committed to Git. Variables must be prefixed PUBLIC_ to be readable in client-side code.

env.env
# Exposed to the browser — never put secrets here
PUBLIC_SITE_URL=https://example.com

# Server-only — safe for secrets, not readable in browser code
API_SECRET_KEY=your_secret_key
Never commit .env

Add .env to .gitignore (it usually is by default). Anything without the PUBLIC_ prefix should stay off the client entirely.

05 · Guide

Pages

How routes are created, which pages ship with Medpro, and how each one is assembled.

Creating a New Page

Astro uses file-based routing: any .astro, .md, or .html file placed in src/pages/ automatically becomes a route matching its file path.

text
src/pages/index.astro                     →  /
src/pages/about.astro                     →  /about
src/pages/checkups.astro                  →  /checkups
src/pages/doctors.astro                   →  /doctors
src/pages/departments.astro               →  /departments
src/pages/contact.astro                   →  /contact
src/pages/404.astro                       →  shown for any unknown URL
src/pages/template-info/style-guide.astro →  /template-info/style-guide
src/pages/template-info/license.astro     →  /template-info/license
src/pages/template-info/changelog.astro   →  /template-info/changelog

To add a page, create a new file in src/pages/ using the layout and structure of an existing, similar page as a starting point. Every Medpro page is a BaseLayout wrapping a list of section components, usually ending with the shared appointment section:

astrosrc/pages/services.astro
---
import BaseLayout from '../layouts/BaseLayout.astro';
import ContactSection from '../components/ContactSection.astro';
---
<BaseLayout title="Services | Medpro" description="Our medical services">
  <h1>Our Services</h1>
  <ContactSection />
</BaseLayout>

If the new page should appear in the header menu, add it to the links array in Navbar.astro (see Navigation).

Editing an Existing Page

Open the relevant file under src/pages/ to see which sections a page uses and in what order. Medpro’s page files are short — the actual text and images live in the imported section components, so edit the component file itself (e.g. src/components/home/Hero.astro for the home hero). Shared sections such as ContactSection and Testimonials appear on several pages, so a change there updates all of them.

Dynamic Routes

Medpro ships no dynamic routes — every page is a single static file. If you add something like individual doctor or blog pages later, files wrapped in square brackets, such as [slug].astro, generate multiple pages from a single template. Astro requires a getStaticPaths() function for these on statically-generated sites:

astrosrc/pages/blog/[slug].astro
---
export async function getStaticPaths() {
  const posts = await import.meta.glob('./posts/*.md');
  return Object.keys(posts).map((path) => ({
    params: { slug: path.split('/').pop().replace('.md', '') },
  }));
}
---

Layouts

Medpro has a single layout, src/layouts/BaseLayout.astro. It imports the global stylesheets, writes the <head> metadata, and renders the top bar, navbar, and footer around each page’s content via a <slot />. A second, named before slot places an element (the pages’ hero background gradients) ahead of the top bar. Simplified:

astrosrc/layouts/BaseLayout.astro
---
const {
  title = 'Medpro — Medical & Healthcare Astro Template',
  description = 'The hospital that cares for life and humanity',
  ogImage = '/images/base_1base.webp',
  navScrollEffect = true,
  noindex = false,
  chrome = true,
} = Astro.props;
---
<html lang="en">
  <head><title>{title}</title> <!-- + description, canonical, OG/Twitter tags --></head>
  <body class="main-body">
    <slot name="before" />
    {chrome && <TopBar />}
    {chrome && <Navbar scrollEffect={navScrollEffect} />}
    <main><slot /></main> <!-- page content is injected here -->
    {chrome && <Footer />}
  </body>
</html>

Page Metadata & the 404 Page

Pass a title and description into BaseLayout on every page for correct browser tabs and search results (see also SEO). A file named 404.astro in src/pages/ is served automatically whenever no route matches; Medpro’s 404 page passes chrome={false} to hide the top bar, navbar, and footer, and noindex={true} to keep it out of search results. The three template-info pages are also noindex and are excluded from the sitemap — delete them (and their footer “Quick links”) if you don’t want them on your live site.

06 · Guide

Components

The building blocks pages are assembled from, and how data flows into them.

Reusable Components

Components live in src/components/, and each one is a full page section written as an .astro file. Five are shared across pages:

ComponentUsed onWhat it renders
TopBar.astroEvery page (via BaseLayout)Address, email, and WhatsApp links above the navbar
Navbar.astroEvery page (via BaseLayout)Logo, menu links, phone number, Appointment button, and the off-canvas mobile menu
Footer.astroEvery page (via BaseLayout)Appointment/WhatsApp buttons, four link columns, copyright, and social icons
ContactSection.astroHome, About, Health Checkup, Doctors, Departments, ContactAppointment heading, contact details, and the appointment form
Testimonials.astroHome, AboutSwiper testimonial carousel with a YouTube video modal

Page-specific sections sit in a subfolder named after the page: home/ (Hero, Treatment, Services, WhyUs, CheckupPlans), about/ (AboutHero, OurStory, Reasons, Values), checkups/ (CheckupPlans, OtherCheckup), doctors/ (Doctors), departments/ (ServicesHero), and template-info/ (a StyleHero + Utility pair for each of the style guide, license, and changelog pages).

Props

Props are the inputs a component accepts, similar to HTML attributes. Medpro is plain JavaScript, so props are read by destructuring Astro.props with default values — there are no TypeScript interfaces. Most section components take no props at all; the ones that do are:

astrosrc/components/ContactSection.astro
---
/** Appointment section + form, shared by every main page. Use headingLevel={1} where it is the page's main heading. */
const { headingLevel = 3 } = Astro.props;
const Heading = 'h' + headingLevel;
---
ComponentPropDefaultEffect
ContactSectionheadingLevel3Heading level of “Get in touch to book your first appointment”; the Contact page passes 1
NavbarscrollEffecttrueTurns the shrink-and-turn-solid effect on scroll on or off
BaseLayouttitle, description, ogImageMedpro defaultsPage title, meta description, and social share image
BaseLayoutnavScrollEffect, noindex, chrometrue, false, truePassed to Navbar; adds noindex meta; shows or hides the top bar, navbar, and footer

Component Composition

Pages are composed from section components rather than written as one long block of markup. This is the complete body of the home page:

astrosrc/pages/index.astro
<BaseLayout title="Medpro — Medical & Healthcare Astro Template" description="The hospital that cares for life and humanity">
  <div class="hero-gradient"></div>
  <Hero />
  <Treatment />
  <Services />
  <WhyUs />
  <CheckupPlans />
  <Testimonials />
  <ContactSection />
</BaseLayout>

Reorder, remove, or repeat these lines to change the page’s layout.

Passing Data to Components

In Astro, props are passed the same way as HTML attributes and read via Astro.props:

astro
---
import ContactSection from '../components/ContactSection.astro';
---
<ContactSection headingLevel={1} />
Where the interactivity lives

Medpro has no React or other UI-framework islands. Interactive behavior — the mobile menu, tabs, carousel, video modal, form demo handler, and animations — is vanilla JavaScript in each component’s own <script> tag, using GSAP and Swiper imported from npm plus the helpers in src/scripts/. Astro bundles and loads these scripts automatically.

07 · Guide

Styling

Where to change colors, type, and spacing without fighting the build.

Global Styles & CSS Variables

Medpro is styled with plain CSS — no Tailwind, Sass, or CSS-in-JS. BaseLayout.astro imports four global stylesheets from src/styles/, in this order:

FilePurpose
normalize.cssCross-browser reset
base-framework.cssBase layout utilities (containers, buttons, forms, nav, tabs) the theme builds on
medpro.cssThe theme itself: @font-face rules, color variables, typography, every section’s styles, and the responsive breakpoints
global.cssSmall additions on top: visible focus outlines, the hidden-until-revealed state for animations, reduced-motion fallbacks, and Swiper base styles

The brand palette is defined once as CSS custom properties at the top of src/styles/medpro.css. Change a value here and it updates everywhere the variable is used:

csssrc/styles/medpro.css
:root {
  --heading-color: #081e29;
  --body: #34454f;
  --white: white;
  --primary: #00a0aa;
  --light-high: #004756;
  --light-low: #d4fffc;
}

Some tints (for example the pale mint #f0fffe section backgrounds) are written as literal hex values further down medpro.css rather than as variables — search the file for a color if changing the variable alone doesn’t catch every instance.

Component Styles

Most of Medpro’s styling is global and class-based (in medpro.css), so section components mainly apply existing classes. Astro components also support scoped <style> blocks — CSS written there only applies to that component, so class names never collide across files. The 404 page uses one:

astrosrc/pages/404.astro
<style>
  .not-found-code {
    color: var(--primary);
  }
</style>

Use <style is:global> when a rule has to reach markup outside the component, as Navbar.astro does for the open state of the mobile menu.

Responsive Design, Typography & Spacing

Typography (headings, the display-title and body---variant-* text classes) and spacing are set in medpro.css, and the base font is Satoshi. Responsive behavior is handled by three max-width media queries at the end of medpro.css: 991px (tablet), 767px (mobile landscape), and 479px (mobile). The navbar collapses into the off-canvas menu at 991px. Prefer adjusting rules inside these existing breakpoints over adding new ones, so the site keeps a consistent rhythm as you edit it. The template is single-theme — there is no dark mode.

Avoid editing dist/

The dist/ folder is generated output — any change made there is overwritten on the next build. Always edit files under src/.

08 · Guide

Images & Assets

Where Medpro keeps its images, and how to swap them for your own.

LocationUse forBehavior
public/images/Every image in the template — photos, logos (medpro-logo.svg, footer-logo.svg), icons, and the default share image base_1base.webpCopied as-is, no processing; referenced by root-relative URLs like /images/medpro-logo.svg
public/ (root)favicon.svg and favicon.icoCopied as-is to the site root
src/assets/Not used by Medpro — optional if you want Astro’s build-time image optimizationOptimized, resized, and content-hashed automatically by the build

Replacing Images

The simplest approach is to overwrite a file in public/images/ with your own image under the same filename. Otherwise, add your file and update the src in the component that uses it. Many photos also have a srcset listing smaller pre-generated versions (files ending in -p-500, -p-800); point those entries at your image too, or remove the srcset and sizes attributes so the browser doesn’t keep loading the old demo files:

astrosrc/components/doctors/Doctors.astro
<!-- before -->
<img src="/images/img_1img.webp" loading="lazy" sizes="..." srcset="/images/img_1-p-500.png 500w, /images/img_1img.webp 704w" alt="doctor's image" class="doctor-image">

<!-- after -->
<img src="/images/dr-jane-doe.webp" loading="lazy" alt="Dr. Jane Doe" class="doctor-image">

Supported Formats & SVGs

Medpro’s images are WebP and PNG photos plus SVG logos and icons, all used through plain <img> tags. Any format the browser supports (JPEG, PNG, WebP, AVIF, GIF, SVG) works the same way from public/. A few icons that need to inherit color via currentColor — the footer buttons, social icons, and the video play button — are inline <svg> markup inside their components instead.

Image Optimization

Files in public/ are not processed by the build, so the demo images were exported already compressed (WebP where possible) with responsive srcset variants. Compress your own images before adding them — a free tool like Squoosh works well. If you’d rather have Astro resize and re-encode images at build time, move them into src/assets/, import them, and render them with the Image component from astro:assets.

Rule of thumb

Keep the template’s convention — images in public/images/, referenced as /images/... — unless you specifically want build-time optimization. Mixing the two approaches on one element (for example, a /images/ URL pointing at a file you moved into src/assets/) is the usual cause of a broken image.

09 · Guide

Fonts & Icons

Swapping typefaces and icon sets without touching every component.

Google Fonts

Medpro doesn’t load any Google Fonts — its only typeface, Satoshi, is self-hosted (see below). To switch to a Google Font, add its <link> tags to the <head> in src/layouts/BaseLayout.astro, then replace Satoshi in the font-family declarations in src/styles/medpro.css:

htmlsrc/layouts/BaseLayout.astro
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">

Local Fonts

Medpro uses Satoshi by Indian Type Foundry (Fontshare license). Five weights — Light (300), Regular (400), Medium (500), Bold (700), and Black (900) — ship as .otf files in public/fonts/ and are declared with @font-face at the top of src/styles/medpro.css:

csssrc/styles/medpro.css
@font-face {
  font-family: Satoshi;
  src: url('/fonts/Satoshi-Bold.otf') format("opentype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

BaseLayout.astro also preloads Satoshi-Bold.otf and Satoshi-Medium.otf so headings render without a flash of fallback text. If you replace the font, update or remove those two <link rel="preload"> tags as well.

Icon Libraries

Medpro doesn’t use an icon library or package. Icons are individual SVG files in public/images/ (for example Phone-icon.svg, mail-Icon.svg, Location-Icon.svg, WhatsApp-Icon.svg), used as <img> tags, plus a handful of inline <svg> icons written directly in Footer.astro and Testimonials.astro. base-framework.css also embeds a tiny medpro-icons font used only for the base framework’s built-in arrow and menu glyphs.

Replacing & Adding Icons

To replace an icon, overwrite its SVG file in public/images/ under the same name, or point the <img src> at a new file. To add one, drop an SVG into public/images/ and reference it as /images/your-icon.svg. For an icon that should follow the surrounding text color, paste the SVG markup inline and set its fill or stroke to currentColor, as the footer icons do.

10 · Beginner Friendly

Content Editing

The fastest, lowest-risk way to make the site say what you want it to say.

New to code?

Everything in this section is plain text or attribute changes — no logic to break. Save the file, and your dev server (from Getting Started) will refresh the browser automatically so you can see the change right away.

Headings, Paragraphs & Buttons

Find the section component that renders the text — check the page file in src/pages/ to see which components it imports — then locate the text between the tags and edit it directly. Buttons are plain links with the primary-btn class, so change the link text and href:

astrosrc/components/home/Hero.astro
<!-- before -->
<h1 class="display-title bold">The hospital that cares for life and humanity</h1>
<a href="/about" class="primary-btn w-button">Discover More</a>

<!-- after -->
<h1 class="display-title bold">Riverside Clinic — family care, close to home</h1>
<a href="/contact" class="primary-btn w-button">Book a visit</a>

Menu links and footer content each live in one component, so you edit them once rather than hunting through every page: header links in the links array in src/components/Navbar.astro, and footer columns, copyright, and social links in src/components/Footer.astro. See Navigation for details.

Cards, Testimonials & Checkup Plans

Testimonials are driven by a data array at the top of src/components/Testimonials.astro, so adding or removing a slide is a matter of editing the list. The same file sets the YouTube video (videoId) that plays in each slide’s modal:

javascriptsrc/components/Testimonials.astro
const videoId = 'r233kDWShkA';
const testimonials = [
  { name: 'Mr. Williams', role: 'Diabetes Patient', quote: 'A wonderful serenity has taken possession of my entire soul, ...' },
  // ...three more entries; `imageFirst: true` puts the video on the left for that slide
];

Other repeating blocks — the doctor cards (doctors/Doctors.astro), checkup plans (home/CheckupPlans.astro and checkups/CheckupPlans.astro), departments (departments/ServicesHero.astro), and services (home/Services.astro) — are written out as markup. Copy an existing card’s block to add one, or delete a block to remove it.

Blog Content & Contact Information

Medpro doesn’t include a blog or Markdown content. The placeholder contact details appear in three components, so update all of them:

  • src/components/TopBar.astro — address (with a Google Maps link), email, and WhatsApp link.
  • src/components/ContactSection.astro — phone number and email beside the appointment form.
  • src/components/Footer.astro — WhatsApp button, copyright name, and social profile links (Facebook, Pinterest, Twitter, Instagram).

The phone number in the header (1800-657-876) is in src/components/Navbar.astro.

12 · Guide

Forms

What ships out of the box, and what still needs a backend.

Forms need somewhere to go

Medpro’s appointment form captures input in the browser, but nothing is sent anywhere: a demo handler shows the “Thank you! Your submission has been received!” message instead of submitting. Delivering submissions to an inbox or database requires a backend endpoint or a third-party form service — none is wired up.

Contact Forms

The appointment form lives in src/components/ContactSection.astro and appears on every main page. It has Name, Phone, Email, Appointment Type (a select with placeholder choices), and Message fields. To make it work, set the form’s action to your form backend, then delete the demo submit handler from the component’s <script>:

astrosrc/components/ContactSection.astro
<!-- before -->
<form name="appointment-form" method="post" action="#" class="contact-form" data-demo-form>

<!-- after (example: Formspree) -->
<form name="appointment-form" method="post" action="https://formspree.io/f/your-form-id" class="contact-form">

Removing the data-demo-form attribute (as above) also stops the demo handler from catching the submit. The handler is the block commented “Demo behaviour only” — leave the initReveals('.contact-section') line above it, which runs the section’s animation. Change the Appointment Type <option> values to your real appointment types while you’re there.

Newsletter Forms

Medpro has no newsletter or email-signup form, and isn’t pre-wired to any email provider. If you add one, the same approach applies: point its action at your provider’s form endpoint (Mailchimp, ConvertKit, and similar services provide one).

Form Validation

Validation uses standard HTML attributes, checked by the browser before submission: Name, Phone, and Email are required, the email field is type="email", the phone field is type="tel", and every field has a maxlength. Users get immediate feedback without a round trip to a server. There is no custom validation script, and Appointment Type and Message are optional.

Third-Party Form Services

If you’d rather not run your own backend, services like Formspree, Getform, or Basin accept form submissions directly from static HTML and forward them to your email — typically a one-line change to the form’s action attribute.

13 · Guide

API & Data

Medpro fetches no external data — this section only matters if you add an API yourself.

No APIs out of the box

All content is written directly in the .astro components, and nothing is fetched at build time or in the browser. The only third-party request is the testimonial video, which loads in a youtube-nocookie.com embed when a visitor clicks play. The guidance below is general advice for adding an API later.

API Configuration

If you add an API, read its URLs and keys from environment variables (see Configuration) rather than hard-coding them, so the same code can point at a staging or production API depending on environment:

env.env
PUBLIC_API_URL=https://example.com/api
PUBLIC_API_KEY=your_api_key
Never expose real credentials

The values above are placeholders. Keep real API keys out of version control, and prefer server-only variables (without the PUBLIC_ prefix) for anything sensitive.

Fetch Requests

javascript
const res = await fetch(`${import.meta.env.PUBLIC_API_URL}/products`, {
  headers: { Authorization: `Bearer ${import.meta.env.PUBLIC_API_KEY}` },
});
const data = await res.json();

Data Structures

Medpro’s only structured data is two plain JavaScript arrays in component frontmatter, which make good models if you later load the same content from an API or CMS:

ArrayFileFields per item
linkssrc/components/Navbar.astrohref (string), label (string)
testimonialssrc/components/Testimonials.astroname, role, quote (strings); optional imageFirst (boolean)

Error Handling

javascript
try {
  const res = await fetch(apiUrl);
  if (!res.ok) throw new Error(`Request failed: ${res.status}`);
  const data = await res.json();
} catch (err) {
  // show a fallback UI state instead of a blank page
  console.error(err);
}
14 · Guide

SEO

Per-page metadata, social previews, and the machine-readable files search engines expect.

Page Title & Meta Description

Every Medpro page passes a unique title and description into BaseLayout — these drive both the browser tab and the snippet shown in search results. Replace the demo wording with your own on each page. An optional ogImage sets the social share image for that page:

astrosrc/pages/about.astro
<BaseLayout
  title="About | Medpro"
  description="The hospital that cares for life and humanity"
  ogImage="/images/about-Image_1about-Image.webp"
>

Canonical URL, Open Graph & Twitter/X Cards

These are already set for you in BaseLayout.astro’s <head>, which uses the site value from astro.config.mjs to build absolute URLs for the canonical link and the share image. The share image defaults to /images/base_1base.webp when a page doesn’t pass ogImage:

astrosrc/layouts/BaseLayout.astro
---
const canonical = new URL(Astro.url.pathname, Astro.site ?? Astro.url);
const image = new URL(ogImage, Astro.site ?? Astro.url);
---
<link rel="canonical" href={canonical} />
<meta property="og:type" content="website" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={image} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={image} />
{noindex && <meta name="robots" content="noindex" />}

Sitemap & Robots.txt

Medpro includes Astro’s official sitemap integration, @astrojs/sitemap, which generates sitemap-index.xml automatically at build time from the site value. Pages under /template-info/ are filtered out, and BaseLayout links the sitemap from every page. The template doesn’t ship a robots.txt — to add one, create public/robots.txt pointing at the sitemap on your domain:

textpublic/robots.txt
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap-index.xml

Structured Data & Semantic HTML

Use landmark elements (<header>, <nav>, <main>, <article>) and a single <h1> per page so both search engines and screen readers can parse the page’s structure. Medpro’s layout wraps page content in <main> and the footer in <footer>. The template ships no JSON-LD structured data — for a clinic, consider adding MedicalOrganization, Hospital, or MedicalClinic schema (with your real address and phone number) in BaseLayout’s <head> for rich results.

15 · Guide

Deployment

Platform-by-platform steps. Confirm your rendering mode first — it changes the build output you deploy.

Static vs. SSR — check this first

Medpro uses Astro’s default static output with no adapter, so npm run build produces plain HTML/CSS/JS in dist/ that any static host can serve. You only need a Node-capable host or a platform adapter if you later switch the project to server-side rendering (SSR). Using the wrong instructions for your rendering mode is the most common deployment mistake.

Vercel

  1. Push the project to a GitHub, GitLab, or Bitbucket repository.
  2. In Vercel, choose Add New → Project and import that repository.
  3. Build command: npm run build · Output directory: dist (Astro static) — Vercel’s Astro preset detects this automatically in most cases.
  4. Medpro needs no environment variables. If you’ve added any in a .env file, set them under Project Settings → Environment Variables.
  5. Click Deploy.

Netlify

tomlnetlify.toml
[build]
  command = "npm run build"
  publish = "dist"

Connect the repository in the Netlify dashboard, confirm these build settings, add any environment variables you’ve introduced under Site configuration → Environment variables (the template itself needs none), and deploy. Medpro doesn’t include a netlify.toml; create one in the project root with the contents above if you want the settings kept in code.

Cloudflare Pages

Connect the repository, set the build command to npm run build and the output directory to dist. For SSR Astro sites, use the official @astrojs/cloudflare adapter instead of the static preset.

GitHub Pages

Set site and base in astro.config.mjs to match your repository URL, then build and publish the dist/ folder to the gh-pages branch (via the official astro build + a deploy action, or manually). GitHub Pages only serves static output — it cannot run an SSR adapter.

Traditional Hosting

Medpro builds to static files, so upload the contents of dist/ to your host’s public web root via FTP/SFTP or your host’s file manager — ordinary shared hosting works. Configure the server to serve 404.html for unknown URLs (for example ErrorDocument 404 /404.html in Apache’s .htaccess). You’d only need a host that runs node continuously (a VPS or Node-compatible host) if you later switch to an SSR adapter.

16 · Guide

Build & Production

What happens when you run build, and a checklist before you ship.

bash
npm run build     # render pages, bundle assets, and write dist/
npm run preview   # serve dist/ locally, exactly as it will run in production

Build Output

The build writes one static HTML file per page (plus 404.html), hashed CSS/JS bundles (including GSAP and Swiper), sitemap-index.xml, and a copy of everything in public/ to dist/. This folder is disposable and regenerated by every build — Medpro’s .gitignore already keeps it out of Git.

Environment Variables in Production

Medpro doesn’t use environment variables, so there’s nothing to configure here by default. If you add some, remember that variables from your local .env are not deployed automatically — each hosting platform requires you to set them again in its dashboard (see Deployment). A missing production variable is one of the most common causes of a build that works locally but fails, or behaves unexpectedly, once deployed.

Production Checklist

  • Run npm run build locally and confirm it completes with no errors.
  • Run npm run preview and click through the main pages.
  • Replace site: 'https://example.com' in astro.config.mjs with your real domain.
  • If you’ve added environment variables, set each one in your hosting platform’s dashboard.
  • Point the appointment form’s action at a real endpoint and remove its demo handler (see Forms).
  • Replace the placeholder address, phone numbers, email, WhatsApp, and social links in TopBar, Navbar, ContactSection, and Footer.
  • Replace the demo doctors, testimonials, and testimonial video with your own.
  • Verify favicon, Open Graph image, and meta descriptions are your own, not the template defaults.
  • Decide whether to keep or delete the /template-info/ pages and their footer links.
17 · Reference

Troubleshooting

The most common problems, in the order you’re likely to hit them.

npm install fails

Cause
Node.js version too old, a corrupted local cache, or a stale lockfile from a different package manager.
Solution
Confirm node --version meets the requirement in Requirements, then run rm -rf node_modules package-lock.json && npm install.

Port already in use

Cause
Another process (often a previous dev server that didn’t shut down cleanly) is already listening on the default port.
Solution
Stop the other process, or start this one on a different port: npm run dev -- --port 4322.

Module not found

Cause
A missing dependency (such as gsap or swiper), or a typo or wrong number of ../ in a relative import path. Medpro uses no path aliases.
Solution
Re-run npm install; check the import path casing matches the file exactly (it matters on Linux build servers); and if you moved a component into or out of a page subfolder, adjust its relative imports.

Images not loading

Cause
A filename or case mismatch (e.g. Phone-icon.svg vs. phone-icon.svg), a srcset still listing a deleted demo file, or an image moved into src/assets/ but still referenced with a /images/ URL.
Solution
Review Images & Assets — files in public/images/ need a root-relative URL like /images/medpro-logo.svg; update or remove srcset/sizes when you swap a photo; imported assets need an import statement.

Styles not loading

Cause
A page isn’t rendered inside BaseLayout (which imports all four stylesheets), the stylesheet import order was changed, or a class name was mistyped.
Solution
Wrap the page in <BaseLayout>; keep the imports in BaseLayout.astro in the order normalize.css, base-framework.css, medpro.css, global.css; and compare your markup’s class names against an existing section.

Sections stay invisible or don’t animate

Cause
Elements with data-reveal are hidden by CSS until their GSAP reveal runs. If a section’s <script> throws an error, or you copied a data-reveal element into a section whose script doesn’t call initReveals(), it never appears. (Medpro has no TypeScript, so there are no type errors to chase.)
Solution
Open the browser console and fix the first error shown. Make sure the section’s script calls initReveals('.your-section-class') from src/scripts/reveal.js (see ContactSection.astro for an example), or remove the data-reveal attribute.

Build fails (but dev server works)

Cause
The dev server only compiles the pages you open, while build renders every page — a broken import or component on a page you didn’t visit during development only shows up at build time.
Solution
Read the full terminal output for the first error (later errors are often side effects of it); fix issues top to bottom and re-run.

Environment variables not working

Cause
Only relevant once you’ve added variables of your own (Medpro uses none): missing the PUBLIC_ prefix for a client-side value, or the dev server wasn’t restarted after editing .env.
Solution
Rename the variable with the PUBLIC_ prefix if it’s used in browser code, then stop and restart npm run dev — env changes aren’t hot-reloaded.

Deployment problems

Cause
Wrong output directory configured on the host, a Node.js version below 22.12 on the build server, or (if you’ve added any) environment variables set locally but not in the platform’s dashboard.
Solution
Re-check the build command (npm run build) and output folder (dist) against Deployment for your platform, set the platform’s Node version to 22.12 or later, and confirm every variable from .env is duplicated there.
18 · Reference

FAQ

Quick answers to the questions we hear most.

How do I install the template?

Extract the ZIP, run your package manager’s install command, then start the dev server. The full walkthrough is in Getting Started.

Which Node.js version should I use?

Node 22.12.0 or later, which Astro 7 requires — see Requirements. The current LTS release is a safe default.

Can I use JavaScript instead of TypeScript?

Medpro is already plain JavaScript — there are no .ts or .tsx files to convert. tsconfig.json is only there for editor tooling. You can add TypeScript later if you want it; Astro supports it with no extra setup.

How do I change colors?

Update the CSS custom properties (--primary, --heading-color, --body, and so on) at the top of src/styles/medpro.css — see Styling.

How do I change fonts?

Replace the Satoshi files in public/fonts/ and their @font-face rules in medpro.css (or add a Google Fonts link), update the font-family declarations, and adjust the two font preloads in BaseLayout.astro — see Fonts & Icons.

How do I replace images?

Overwrite the file in public/images/ under the same name, or update the src (and srcset) in the component — see Images & Assets.

How do I add a new page?

Add a file to src/pages/ that wraps its sections in BaseLayout; the route is created automatically. Add it to the links array in Navbar.astro if it belongs in the menu — see Pages.

How do I deploy the template?

Platform-specific steps for Vercel, Netlify, Cloudflare Pages, GitHub Pages, and traditional hosts are in Deployment.

Can I use the template commercially?

[State your license terms here — e.g. standard vs. extended license — and link to the full license text.] Separately, the demo images come from Freepik, Unsplash, and Pexels, and the Satoshi font comes from Fontshare. Links to each license are on the template’s /template-info/license page. Replace the demo content with your own before publishing.

Where can I get support?

See the Support section for contact details and what to include in a request.

19 · Reference

Changelog

Every notable change, newest first. Add a new entry above the last one for each release.

Version 0.0.1[Release date]
  • AddedInitial release: Home, About, Health Checkup, Doctors, Departments, and Contact pages, plus a 404 page and style guide, license, and changelog pages.
  • AddedGSAP scroll and hover animations, a Swiper testimonial carousel with a video modal, accessible tabs, and an off-canvas mobile menu.
  • AddedSEO, Open Graph, and Twitter meta on every page, plus a sitemap via @astrojs/sitemap.
Keeping this current

Copy the markup for one entry above, update the version number, date, and bullet list, and place it at the top of this section for each new release.

20 · Reference

Support

Stuck on something this guide didn’t cover? Here’s how to reach us.

Documentation

Most questions are answered somewhere in this guide — try the search (Ctrl K) before reaching out.

Back to top

Contact support

Email hello@rnnstudio.com or reach us through our contact form.

Contact support

Support hours

We’re based in India and available Monday–Friday, 10am–7pm IST. Expect a response within 24 hours.

What to Include in a Support Request

The fastest way to get a useful answer is to include the details below in your first message:

text
When contacting support, please include:

- Template name and version
- Browser (and version)
- Operating system
- Node.js version (node --version)
- The exact error message
- Steps to reproduce the problem