# Redesign Documentation & Handoff Guide **Project**: WorkRoot IT Solutions — Company Site **Date**: 2026-03-21 **Author**: documentation-writer agent **Status**: Production-ready (98/100 Lighthouse avg) --- ## Table of Contents 1. [Project Overview](#1-project-overview) 2. [Design System](#2-design-system) 3. [Component Library](#3-component-library) 4. [Page Architecture](#4-page-architecture) 5. [Animation System](#5-animation-system) 6. [Contact Page Deep Dive](#6-contact-page-deep-dive) 7. [Theme System](#7-theme-system) 8. [Maintenance Guidelines](#8-maintenance-guidelines) 9. [Future Enhancement Recommendations](#9-future-enhancement-recommendations) 10. [Quick Reference](#10-quick-reference) --- ## 1. Project Overview ### Technology Stack | Layer | Technology | Notes | |-------|-----------|-------| | Framework | Astro (SSR) | Node.js adapter, standalone mode | | Styling | Tailwind CSS + custom CSS | Extended with design tokens | | Typography | Plus Jakarta Sans + JetBrains Mono | Self-hosted via Google Fonts | | Animations | Native Intersection Observer | Zero external dependencies | | Image Optimization | Sharp (via Astro) | Auto WebP conversion | | Error Tracking | Sentry | Configured in `src/utils/sentry.ts` | | Analytics | Custom wrapper | `src/utils/analytics.ts` | | PWA | Service Worker + manifest | Install prompt component | | SEO | Custom component | Structured data (Schema.org) | ### Site URL ``` Production: https://workroot.in Server: 0.0.0.0:10000 (standalone Node.js) ``` ### Project Structure ``` src/ ├── components/ │ ├── Analytics.astro │ ├── Footer.astro │ ├── Header.astro │ ├── LazyImage.astro │ ├── OptimizedImage.astro │ ├── PWAInstallPrompt.astro │ ├── SEO.astro │ └── ui/ │ ├── Badge.astro │ ├── Card.astro │ └── SectionHeader.astro ├── layouts/ │ └── BaseLayout.astro ├── pages/ │ ├── index.astro │ ├── about.astro │ ├── services.astro │ ├── portfolio.astro │ ├── contact.astro ← Primary redesign │ ├── privacy.astro │ └── terms.astro ├── styles/ │ └── global.css ← Design tokens + component classes └── utils/ ├── analytics.ts ├── animations.ts ← Scroll-reveal utilities ├── imageUtils.ts ├── logger.ts ├── sentry.ts └── seo.ts ``` --- ## 2. Design System ### Color Palette Defined in both `tailwind.config.mjs` (Tailwind classes) and `src/styles/global.css` (CSS custom properties). #### Primary — Cyan | Token | Value | Usage | |-------|-------|-------| | `--color-primary` | `#0891b2` | Buttons, links, icons, accents | | `primary-50` | `#ecfeff` | Light backgrounds, hover states | | `primary-100` | `#cffafe` | Subtle highlights | | `primary-500` | `#06b6d4` | Mid-tone | | `primary-600` | `#0891b2` | Default (same as token) | | `primary-700` | `#0e7490` | Hover states, borders | | `primary-900` | `#164e63` | Dark text on light primary | #### Secondary — Slate | Token | Value | Usage | |-------|-------|-------| | `--color-secondary` | `#1e293b` | Body text, dark backgrounds | | `secondary-50` | `#f8fafc` | Page backgrounds, cards | | `secondary-100` | `#f1f5f9` | Surface cards | | `secondary-600` | `#475569` | Muted body text | | `secondary-700` | `#334155` | Default body text | | `secondary-800` | `#1e293b` | Headings, labels | | `secondary-900` | `#0f172a` | High-contrast text | #### Accent — Amber | Token | Value | Usage | |-------|-------|-------| | `--color-accent` | `#f59e0b` | Highlights, CTAs, warnings | | `accent-50` | `#fffbeb` | Very light backgrounds | | `accent-400` | `#fbbf24` | Hover states | | `accent-500` | `#f59e0b` | Default (same as token) | | `accent-600` | `#d97706` | Pressed/active states | ### Typography ```css /* Font Families */ --font-sans: 'Plus Jakarta Sans', system-ui, sans-serif; --font-mono: 'JetBrains Mono', monospace; /* Display Sizes (responsive clamp) */ display-xl: clamp(3rem, 6vw, 6rem) /* Hero headlines */ display-lg: clamp(2.25rem, 4vw, 4.5rem) /* Section headlines */ ``` **Usage Pattern**: - `font-sans` — All UI text, body copy, labels - `font-mono` — Code blocks, technical values, stats - `font-display` — NOT a separate family; use `font-sans font-bold` at display sizes ### Spacing | Token | Value | Tailwind Class | Usage | |-------|-------|----------------|-------| | `--spacing-section` | `6rem` | `py-24` | Major section padding | | `--spacing-section-sm` | `4rem` | `py-16` | Smaller section padding | | `--spacing-section-lg` | `8rem` | `py-32` | Hero / featured sections | ### Border Radius | Token | Value | Usage | |-------|-------|-------| | `--radius-sm` | `8px` | Inputs, badges, tags | | `--radius-md` | `12px` | Buttons, small cards | | `--radius-lg` | `16px` | Standard cards | | `--radius-xl` | `24px` | Feature cards, modals | | `--radius-full` | `9999px` | Pills, avatars, icons | | `rounded-card` | `1rem` | Card.astro default | | `rounded-card-lg` | `1.5rem` | Service cards | ### Shadows | Token | Usage | |-------|-------| | `shadow-sm` | Subtle depth on inputs | | `shadow-card` | Default card elevation | | `shadow-card-hover` | Hovered card elevation | | `shadow-primary-glow` | Primary color glow effect | | `shadow-accent-glow` | Accent color glow effect | ### Transitions | Token | Value | Usage | |-------|-------|-------| | `--transition-fast` | `150ms` | Hover tints, focus rings | | `--transition-base` | `200ms` | Button states, icon transforms | | `--transition-slow` | `300ms` | Card lifts, panel slides | | `--transition-slower` | `500ms` | Page-level transitions | ### Background Gradients (Tailwind `bg-*`) | Class | Usage | |-------|-------| | `bg-hero-dark` | Hero sections with dark gradient | | `bg-cta-dark` | CTA/banner sections | | `bg-primary-gradient` | Primary-to-transparent gradient | | `bg-primary-gradient-br` | Bottom-right variant | | `bg-surface-gradient` | Light surface backgrounds | | `bg-card-gradient` | Card hover gradients | --- ## 3. Component Library ### `Badge.astro` — Eyebrow Label Used above section headings as visual callouts. ```astro --- import Badge from '../components/ui/Badge.astro'; --- ``` **Props:** | Prop | Type | Default | Description | |------|------|---------|-------------| | `label` | `string` | required | Text to display | | `variant` | `'primary' \| 'primary-dark' \| 'accent' \| 'secondary'` | `'primary'` | Color theme | | `class` | `string` | — | Extra Tailwind classes | **Variants:** - `primary` — Cyan on light backgrounds (most pages) - `primary-dark` — Light text on dark/hero sections - `accent` — Amber/warm for highlights - `secondary` — Neutral slate for subtle labeling --- ### `Card.astro` — Versatile Card Wrapper ```astro --- import Card from '../components/ui/Card.astro'; ---

Title

Content

``` **Props:** | Prop | Type | Default | Description | |------|------|---------|-------------| | `variant` | `'feature' \| 'service' \| 'surface' \| 'dark' \| 'plain'` | `'feature'` | Visual style | | `padding` | `string` | variant-based | Override padding | | `class` | `string` | — | Extra classes | **Variant Details:** | Variant | Background | Hover Effect | Default Padding | Use Case | |---------|-----------|--------------|-----------------|----------| | `feature` | Gradient (white→primary-50) | Lift + border glow | `p-8` | Benefits, features | | `service` | White | Shadow lift | `p-10` | Services grid | | `surface` | `secondary-50` | Subtle border | `p-6` | Contact info, sidebar | | `dark` | Glassmorphism | Border highlight | `p-8` | Dark section cards | | `plain` | None | None | None | Full customization | --- ### `SectionHeader.astro` — Section Heading Block Used at the top of each major page section. ```astro --- import SectionHeader from '../components/ui/SectionHeader.astro'; --- ``` **Props:** | Prop | Type | Default | Description | |------|------|---------|-------------| | `badge` | `string` | required | Eyebrow text (uses Badge.astro) | | `title` | `string` | required | H2 heading text | | `description` | `string` | — | Optional paragraph below | | `theme` | `'light' \| 'dark'` | `'light'` | Adapts text color | | `badgeColor` | `'primary' \| 'accent'` | `'primary'` | Badge variant | | `maxWidth` | `string` | `'max-w-3xl'` | Width constraint on description | | `class` | `string` | — | Extra classes | --- ### `BaseLayout.astro` — Page Wrapper Wraps every page. Handles: SEO meta tags, Organization structured data, global fonts, analytics, error tracking, PWA prompt, header, footer, skip-to-content link. ```astro --- import BaseLayout from '../layouts/BaseLayout.astro'; --- ``` --- ### `SEO.astro` — Meta Tags & Structured Data Included via `BaseLayout.astro`. Generates: - `` and `<meta name="description">` - Open Graph (Facebook/LinkedIn) tags - Twitter Card tags - Canonical URL - JSON-LD structured data (WebPage schema) --- ### `LazyImage.astro` / `OptimizedImage.astro` For images within page content. ```astro <!-- Lazy loaded with blur placeholder --> <LazyImage src="/hero.jpg" alt="Description" width={800} height={450} /> <!-- Optimized with Sharp (auto WebP) --> <OptimizedImage src="/photo.jpg" alt="Description" width={600} height={400} /> ``` --- ### CSS-Only Components (via `global.css`) These are plain HTML elements styled via class names — no Astro component required. #### Buttons ```html <!-- Primary CTA --> <a href="/contact" class="btn-primary">Get Started</a> <!-- Secondary/Outline --> <a href="/portfolio" class="btn-secondary">View Work</a> <!-- Accent (amber) --> <button class="btn-accent">Highlight Action</button> <!-- Ghost (transparent) --> <button class="btn-ghost">Learn More</button> <!-- Large variants for hero sections --> <a href="/contact" class="btn-primary-lg">Start a Project</a> <a href="/services" class="btn-inverse-lg">View Services</a> ``` #### Form Elements ```html <label class="form-label" for="name">Your Name</label> <input class="form-input" id="name" type="text" /> <span class="form-error">This field is required.</span> <!-- Error state on input --> <input class="form-input form-input-error" id="email" type="email" /> ``` #### Section Patterns ```html <!-- Light section --> <div class="section-header"> <p class="section-title">Main Heading</p> <p class="section-description">Supporting text...</p> </div> <!-- Dark/inverse section --> <div class="section-header"> <p class="section-title-inverse">Main Heading</p> <p class="section-description-inverse">Supporting text...</p> </div> ``` #### Decorative Elements ```html <!-- Blobs (absolute-positioned background shapes) --> <div class="blob blob-primary"></div> <div class="blob blob-accent"></div> <!-- Grid overlay (semi-transparent dot grid) --> <div class="grid-overlay"></div> <!-- Gradient text --> <span class="gradient-text">Highlighted Words</span> <span class="gradient-text-primary">Also works</span> ``` --- ## 4. Page Architecture ### Section Pattern Every major page section follows this structure: ```astro <section class="py-24 bg-white relative overflow-hidden"> <!-- Optional decorative blobs --> <div class="blob blob-primary top-0 left-0"></div> <div class="container-wrapper"> <!-- SectionHeader --> <SectionHeader badge="Label" title="Section Title" description="Optional description" /> <!-- Content grid --> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mt-16"> <!-- Cards or content --> </div> </div> </section> ``` ### Page Layout Zones | Zone | Background | Typical Content | |------|-----------|-----------------| | Hero | `bg-hero-dark` (dark gradient) | Headline, subtext, CTAs, trust stats | | Features | `bg-white` | Cards with icons | | Services | `bg-secondary-50` | Service cards grid | | Testimonials | `bg-hero-dark` | Quote cards | | CTA Banner | `bg-cta-dark` | Headline + 2 CTA buttons | | Contact | `bg-secondary-50` | Form + sidebar | | Footer | `bg-secondary-900` | Nav links, social, copyright | ### Responsive Breakpoints Uses Tailwind defaults: - `sm`: 640px — Small phones → landscape - `md`: 768px — Tablets - `lg`: 1024px — Laptops - `xl`: 1280px — Desktops - `2xl`: 1536px — Large monitors **Grid patterns used across pages:** ``` Hero: Single column centered Features: 1 col → 2 col → 3 col (sm/md/lg) Services: 1 col → 2 col → 3 col Contact: 1 col → 3+2 col split (lg) Portfolio: 1 col → 2 col → 3 col with filters ``` --- ## 5. Animation System ### How It Works Animations use the native **Intersection Observer API** — no JavaScript library needed. The system is defined in two files: - `src/utils/animations.ts` — JavaScript observer logic - `src/styles/global.css` — CSS transitions and keyframes ### Usage Pattern Add `data-animate` and optional `data-delay` to any element: ```html <div data-animate="fade-up">Animates when scrolled into view</div> <div data-animate="fade-up" data-delay="200">Delayed by 200ms</div> <div data-animate="scale-up" data-duration="slow">Slower duration</div> ``` Then initialize in the page's `<script>` tag: ```javascript import { initScrollReveal } from '../utils/animations'; document.addEventListener('DOMContentLoaded', () => { initScrollReveal(); }); ``` Or use `initAllAnimations()` to enable everything: ```javascript import { initAllAnimations } from '../utils/animations'; document.addEventListener('DOMContentLoaded', initAllAnimations); ``` ### Animation Types (`data-animate` values) | Value | Effect | |-------|--------| | `fade-up` | Fade in + slide up 30px | | `fade-down` | Fade in + slide down 30px | | `fade-left` | Fade in + slide from right | | `fade-right` | Fade in + slide from left | | `fade-in` | Fade in only | | `scale-up` | Scale from 0.95 → 1.0 with fade | | `zoom-in` | Scale from 0.8 → 1.0 with fade | ### Delay Classes (`data-delay` values) `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800` (milliseconds) Use to stagger card grids: ```html <div class="grid grid-cols-3 gap-8"> <div data-animate="fade-up" data-delay="0">Card 1</div> <div data-animate="fade-up" data-delay="150">Card 2</div> <div data-animate="fade-up" data-delay="300">Card 3</div> </div> ``` ### Duration Variants (`data-duration` values) | Value | Duration | |-------|---------| | `fast` | 400ms | | (default) | 600ms | | `slow` | 900ms | ### Reduced Motion All animations automatically respect `prefers-reduced-motion: reduce`. Elements marked with `data-animate` are revealed immediately without transitions when this preference is set. ### Other Animation Utilities | Function | Description | |----------|-------------| | `initCounters()` | Animate `[data-counter]` elements from 0 to target value | | `initButtonRipple()` | Cursor-following radial highlight on `.btn-ripple` buttons | | `initProgressBars()` | Fill `.progress-bar` elements to `--progress-width` CSS variable | ### Counter Example ```html <span data-counter="150" data-counter-suffix="+" data-counter-duration="2000" class="text-4xl font-bold" >0</span> ``` --- ## 6. Contact Page Deep Dive The contact page (`src/pages/contact.astro`, ~1029 lines) is the most feature-rich redesigned page and serves as the reference implementation for advanced patterns. ### Page Sections 1. **Hero** — Dark gradient with grid overlay, trust statistics, scroll-reveal 2. **Contact Form + Sidebar** — 3-column form + 2-column sidebar on `lg` breakpoints 3. **FAQ** — Collapsible details/summary 4. **CTA Banner** — Dark gradient with dual CTAs ### Form Architecture The contact form uses no external form library. All behavior is plain JavaScript. #### Spam Protection (Honeypot) ```html <!-- Hidden field — bots fill it, humans don't --> <div style="position: absolute; left: -9999px; opacity: 0" aria-hidden="true"> <input type="text" name="website" tabindex="-1" autocomplete="off" /> </div> ``` Server-side: check that `website` field is empty before processing. #### Budget Selector (Radio as Chips) The budget options render as visual chip buttons but use `<input type="radio">` under the hood for accessibility: ```html <div class="flex flex-wrap gap-3"> <label class="budget-option"> <input type="radio" name="budget" value="under-5k" class="sr-only" /> <span>Under $5K</span> </label> </div> ``` JavaScript adds/removes the `selected` class when a chip is clicked, and the CSS handles the visual transformation from neutral to active. #### Form Validation Regex patterns used: ```javascript const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; const phoneRegex = /^[\+]?[1-9][\d]{0,15}$/; ``` Validation fires on `blur` (field leave) and `submit`. Visual feedback via `.form-input-error` class and a sibling error `<span class="form-error">`. #### Character Counter ```html <textarea id="message" maxlength="2000" data-counter-target="message-counter" ></textarea> <span id="message-counter">0/2000</span> ``` JavaScript updates the counter text on `input` events. #### Toast Notifications ```javascript function showToast(message, type = 'success') { const toast = document.getElementById('toast'); // Set message text, apply type class, show with transition // Auto-hide after 5000ms } ``` The toast element is always in the DOM (`position: fixed, bottom-right`) but visually hidden until triggered. #### Form States | State | UI Change | |-------|-----------| | Default | Normal form | | Loading | Button shows spinner, disabled | | Success | Overlay replaces form, shows success message | | Error | Toast notification, form re-enabled | ### Sidebar Components #### Contact Info Cards Four cards (Visit Us, Call Us, Email Us, Business Hours) using `card-surface` variant. Each has: - Color-coded icon container (primary, accent, etc.) - Title + content - Hover lift effect #### Map Embed A static map image with an overlay on hover. Contains a floating pin animation: ```css @keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } } ``` The hover overlay prompts "Open in Google Maps" with a link. #### Social Links ```html <a href="https://linkedin.com/..." class="social-link group"> <!-- SVG icon --> <span>LinkedIn</span> </a> ``` Custom hover effect: icon rotates slightly, text shifts right. ### FAQ Section Uses native `<details>/<summary>` HTML for zero-JS accordion behavior: ```html <details class="faq-item"> <summary class="faq-question"> Question text <span class="faq-icon"><!-- chevron SVG --></span> </summary> <div class="faq-answer">Answer text</div> </details> ``` CSS handles the open/close transition via `details[open]` selector. The chevron rotates 180° when open. ### Analytics Events The contact page fires analytics events for key interactions: ```javascript // On budget chip select trackEvent('budget_selected', { budget: value }); // On form submit (success) trackEvent('form_submitted', { budget: selectedBudget }); // On social link click trackEvent('social_click', { platform: 'linkedin' }); ``` --- ## 7. Theme System The site ships a full **dark / light theme system** with FOUC prevention, localStorage persistence, OS preference detection, and WCAG AAA contrast compliance. ### Key Files | File | Role | |------|------| | `src/styles/design-tokens.css` | All color tokens (`:root` light + `html.dark` overrides) | | `src/components/ThemeToggle.astro` | Sun/moon toggle button in the header | | `src/layouts/BaseLayout.astro` | Blocking inline script (prevents flash of wrong theme) | ### How It Works (Summary) 1. A synchronous inline script in `<head>` reads `localStorage.getItem('theme')` or `prefers-color-scheme` and adds `html.dark` before the first CSS paint — eliminating FOUC. 2. All colors are CSS custom properties (`--color-*`). `html.dark` overrides them for the dark palette. 3. Tailwind's `dark:` class variant targets `html.dark` for utility classes. 4. `ThemeToggle.astro` handles click events, syncs all toggle instances, updates ARIA state, announces to screen readers, and updates `<meta name="theme-color">`. ### Developer Quick Start ```html <!-- ✅ Use semantic tokens --> <div style="background: var(--color-surface-raised); color: var(--color-text-primary);"> <!-- ✅ Use Tailwind dark: variants --> <div class="bg-white dark:bg-secondary-800 text-secondary-700 dark:text-secondary-300"> ``` ### Full Documentation See **[THEME_SYSTEM_GUIDE.md](./THEME_SYSTEM_GUIDE.md)** for: - Complete design token reference - Step-by-step guide for adding theme support to new components - Troubleshooting guide (FOUC, contrast issues, screen reader support, etc.) - Accessibility and WCAG compliance details - Performance notes --- ## 8. Maintenance Guidelines ### Adding a New Page 1. Create `src/pages/new-page.astro` 2. Use `BaseLayout.astro` as wrapper with SEO props 3. Follow the section pattern (container-wrapper, SectionHeader, content) 4. Import and initialize animations in the `<script>` tag 5. Update `Header.astro` navigation links 6. Update `Footer.astro` if it appears in site map 7. Update `src/pages/sitemap.astro` and `sitemap.xml.ts` ### Adding a New Color 1. Add to `tailwind.config.mjs` under `theme.extend.colors` 2. Add CSS custom property to `src/styles/global.css` in `:root` 3. Create any needed component classes in `global.css` ### Adding a New Animation 1. Define keyframe in `src/styles/global.css` under `@keyframes` 2. Add animation class in Tailwind config `theme.extend.animation` 3. Add `[data-animate="new-type"]` CSS in `global.css` if using scroll-reveal 4. Always add `@media (prefers-reduced-motion: reduce)` override ### Modifying the Contact Form - **Validation rules**: Edit the regex patterns in the `<script>` section of `contact.astro` - **Budget options**: Add/remove `<label class="budget-option">` items - **FAQ entries**: Add `<details>` blocks in the FAQ section - **Server handling**: The form POSTs to `/api/contact` — edit `src/pages/api/contact.ts` ### Performance Checklist (before deploy) - [ ] New images use `<OptimizedImage>` or `<LazyImage>` components - [ ] Large sections use `data-animate` for scroll-reveal (avoid layout shift) - [ ] No inline `style` tags with large CSS blocks — use `global.css` classes - [ ] External resources are from whitelisted domains only - [ ] Run `npm run build` and check bundle size (target: <300KB client JS) - [ ] Run Lighthouse (target: 90+ on all metrics) ### Dependency Updates Key dependencies to keep updated: - `astro` — Major versions may need config migration - `@astrojs/tailwind` — Follows Tailwind CSS releases - `tailwindcss` — v3.x series; v4 will require config rewrite - `@sentry/browser` — Security patches important --- ## 9. Future Enhancement Recommendations ### High Priority #### 1. Blog / Content Section The `src/content/blog/` directory exists but no blog listing page is implemented. Recommended approach: - Create `src/pages/blog/index.astro` with card grid - Create `src/pages/blog/[slug].astro` for individual posts - Use Astro Content Collections (already configured) - Leverage existing `SectionHeader`, `Card`, `Badge` components #### 2. Case Study Modal → Dedicated Pages Portfolio case studies currently open in a JavaScript modal. For better SEO and shareability: - Create `src/pages/portfolio/[slug].astro` - Add structured data (CreativeWork schema) per case study - Implement smooth navigation with View Transitions API #### 3. Form Backend Enhancement Current contact form uses a simple API route. Consider: - Email notification via SendGrid or Resend - CRM integration (HubSpot, Pipedrive) - File attachment support for design briefs - Multi-step form wizard for complex project scoping ### Medium Priority #### 4. i18n / Localization Astro has built-in i18n routing. For a future multi-language site: - Use `src/pages/[locale]/` routing - Store copy in `src/content/` or external CMS - Update `astro.config.mjs` with `i18n` config #### 5. Dark Mode ✅ Implemented Dark mode is fully implemented. See [THEME_SYSTEM_GUIDE.md](./THEME_SYSTEM_GUIDE.md) for developer and user documentation. #### 6. Animation Performance Current scroll-reveal uses a single Intersection Observer. For pages with many animated elements: - Consider virtualized animation queuing (pause observer after element leaves viewport) - Profile with Chrome DevTools Performance tab on low-end devices - The `data-duration="fast"` option is available for elements needing snappier reveals ### Low Priority #### 7. Component Storybook The `Badge`, `Card`, and `SectionHeader` components are well-isolated. A Storybook setup would: - Provide a visual component library - Document all variant combinations - Enable designer handoff via Storybook's design tools #### 8. Automated Visual Regression Add Playwright screenshot tests for critical pages: ```typescript // tests/visual.spec.ts test('contact page matches snapshot', async ({ page }) => { await page.goto('/contact'); await expect(page).toHaveScreenshot('contact.png'); }); ``` Use `--update-snapshots` flag after intentional design changes. #### 9. Edge Caching Currently SSR renders on every request. For pages with low dynamic content: - Use Astro's `export const prerender = true` for static generation - Or add `Cache-Control` headers in the Node.js middleware - The about, privacy, and terms pages are good candidates --- ## 10. Quick Reference ### Common Patterns #### Hero Section ```astro <section class="bg-hero-dark py-32 relative overflow-hidden"> <div class="grid-overlay"></div> <div class="blob blob-primary top-0 right-0"></div> <div class="container-wrapper text-center"> <Badge label="Eyebrow Text" variant="primary-dark" /> <h1 class="display-xl text-white font-bold mt-4"> Hero <span class="gradient-text">Headline</span> </h1> <p class="text-xl text-secondary-300 max-w-2xl mx-auto mt-6"> Supporting description text. </p> <div class="flex gap-4 justify-center mt-10"> <a href="/contact" class="btn-primary-lg">Primary CTA</a> <a href="/portfolio" class="btn-inverse-lg">Secondary CTA</a> </div> </div> </section> ``` #### Feature Card Grid ```astro <section class="py-24 bg-white"> <div class="container-wrapper"> <SectionHeader badge="Features" title="Why Choose Us" /> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mt-16"> {features.map((feature, i) => ( <Card variant="feature" data-animate="fade-up" data-delay={i * 100}> <div class="icon-container icon-md mb-4"> <!-- SVG icon --> </div> <h3 class="text-xl font-semibold text-secondary-800">{feature.title}</h3> <p class="text-secondary-600 mt-2">{feature.description}</p> </Card> ))} </div> </div> </section> ``` #### CTA Banner ```astro <section class="bg-cta-dark py-24 relative overflow-hidden"> <div class="container-wrapper text-center"> <h2 class="display-lg text-white font-bold"> Ready to <span class="gradient-text">Get Started?</span> </h2> <p class="text-secondary-300 text-xl max-w-2xl mx-auto mt-6"> Supporting text here. </p> <div class="flex gap-4 justify-center mt-10"> <a href="/contact" class="btn-primary-lg">Start a Project</a> <a href="/services" class="btn-inverse-lg">View Services</a> </div> </div> </section> ``` ### Class Cheat Sheet ``` Layout: container-wrapper Max-width container with responsive padding Buttons: btn-primary Solid cyan button btn-secondary Outline cyan button btn-accent Solid amber button btn-ghost Transparent/white hover btn-primary-lg Large solid (hero sections) btn-inverse-lg Large outline white (dark backgrounds) Badges: badge badge-primary Cyan pill (light bg) badge badge-primary-dark Cyan pill (dark bg) badge badge-accent Amber pill badge badge-secondary Slate pill Forms: form-label Label text form-input Text input / textarea / select form-input-error Error state for inputs form-error Error message text Typography: gradient-text Cyan gradient text gradient-text-primary Alternate gradient section-title Section H2 on light bg section-description Section P on light bg section-title-inverse Section H2 on dark bg section-description-inverse Section P on dark bg Decorative: blob blob-primary Cyan background blob blob blob-accent Amber background blob grid-overlay Dot grid overlay Animations: data-animate="fade-up" Scroll reveal animation data-delay="200" Delay in ms (100-800) data-counter="100" Animated counter ``` --- *This document was generated by the documentation-writer agent on 2026-03-21. Update this document when making significant design changes to the site.*