# 🌐 Web Pages


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

## 🎯 Overview

<table>
<colgroup>
<col style="width: 32%" />
<col style="width: 38%" />
<col style="width: 29%" />
</colgroup>
<thead>
<tr>
<th>Category</th>
<th>Components</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td>🎬 Hero</td>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#herosection"><code>HeroSection</code></a></td>
<td>Full-width landing hero with CTAs</td>
</tr>
<tr>
<td>✨ Features</td>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#featuresgrid"><code>FeaturesGrid</code></a></td>
<td>Icon cards showcasing product features</td>
</tr>
<tr>
<td>💰 Pricing</td>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#pricingsection"><code>PricingSection</code></a></td>
<td>Single pricing card with feature checklist</td>
</tr>
<tr>
<td>❓ FAQ</td>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#faqsection"><code>FAQSection</code></a></td>
<td>Expandable FAQ using Details/Summary</td>
</tr>
<tr>
<td>🦶 Footer</td>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#pagefooter"><code>PageFooter</code></a></td>
<td>Multi-column footer with social links</td>
</tr>
<tr>
<td>🧭 Nav</td>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#landingnavbar"><code>LandingNavBar</code></a></td>
<td>Sticky navbar with brand and CTAs</td>
</tr>
<tr>
<td>📄 Pages</td>
<td><code>LandingPage</code>, <code>LandingPageV2</code></td>
<td>Complete landing page compositions</td>
</tr>
</tbody>
</table>

------------------------------------------------------------------------

## 🏗️ Architecture

    ┌─────────────────────────────────────────────────────────┐
    │                    Landing Page                          │
    ├─────────────────────────────────────────────────────────┤
    │  LandingNavBar (sticky, blur)                           │
    │  ├─ Brand + Navigation Links + CTA Actions              │
    ├─────────────────────────────────────────────────────────┤
    │  HeroSection                                            │
    │  ├─ Title + Subtitle + Primary/Secondary CTAs           │
    ├─────────────────────────────────────────────────────────┤
    │  FeaturesGrid                                           │
    │  ├─ 3-column responsive cards with icons                │
    ├─────────────────────────────────────────────────────────┤
    │  PricingSection                                         │
    │  ├─ Centered pricing card with feature bullets          │
    ├─────────────────────────────────────────────────────────┤
    │  FAQSection                                             │
    │  ├─ Expandable Details/Summary items                    │
    ├─────────────────────────────────────────────────────────┤
    │  PageFooter                                             │
    │  ├─ Multi-column links + Copyright + Social icons       │
    └─────────────────────────────────────────────────────────┘

------------------------------------------------------------------------

## 📚 Quick Reference

``` python
# Complete landing page in one call
LandingPage(
    brand_name="MyBrand",
    hero_title="Welcome",
    hero_subtitle="Build faster",
    features=[{'icon': 'speed', 'title': 'Fast', 'description': '...'}],
    faqs=[{'question': 'Q?', 'answer': 'A'}]
)
```

<details class="code-fold">
<summary>Code</summary>

``` python
import socket
import time
import subprocess

def kill_process_on_port(port):
    """Kill any process using the specified port on Windows"""
    try:
        result = subprocess.run(
            f'netstat -ano | findstr :{port}',
            shell=True, capture_output=True, text=True
        )
        
        if result.stdout:
            lines = result.stdout.strip().split('\n')
            for line in lines:
                if 'LISTENING' in line:
                    pid = line.strip().split()[-1]
                    subprocess.run(f'taskkill /PID {pid} /F', shell=True, capture_output=True)
                    print(f"✓ Killed process {pid} on port {port}")
                    time.sleep(0.5)
                    return True
        return False
    except Exception as e:
        print(f"⚠ Could not kill process on port {port}: {e}")
        return False

def find_available_port(start_port=5000, max_attempts=10):
    """Find an available port starting from start_port"""
    for port in range(start_port, start_port + max_attempts):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            try:
                s.bind(('', port))
                return port
            except OSError:
                continue
    raise RuntimeError(f"Could not find an available port in range {start_port}-{start_port+max_attempts}")

# Stop existing server if running
if 'server' in globals(): 
    try:
        server.stop()
        time.sleep(0.5)
    except:
        pass

# Try to kill any process on preferred port, then find available port
preferred_port = 7020
kill_process_on_port(preferred_port)
port = find_available_port(preferred_port)

app = FastHTML(hdrs=MatTheme.blue.headers(title="Page Snippets", mode="dark"))
rt = app.route

try:
    server = JupyUvi(app, port=port)
    preview = partial(HTMX, app=app, port=port)
    print(f"✓ Server running on port {port}")
except Exception as e:
    print(f"✗ Failed to start server: {e}")
    raise
```

</details>

<script>
document.body.addEventListener('htmx:configRequest', (event) => {
    if(event.detail.path.includes('://')) return;
    htmx.config.selfRequestsOnly=false;
    event.detail.path = `${location.protocol}//${location.hostname}:7020${event.detail.path}`;
});
</script>

    ✓ Server running on port 7020

## 🎬 Hero Section

<table>
<colgroup>
<col style="width: 55%" />
<col style="width: 45%" />
</colgroup>
<thead>
<tr>
<th>Component</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#herosection"><code>HeroSection</code></a></td>
<td>Full-width hero with title, subtitle, and CTA buttons</td>
</tr>
</tbody>
</table>

**Features:** BeerCSS-first styling, optional secondary CTA, custom
CSS/JS hooks

------------------------------------------------------------------------

<a
href="https://github.com/abhisheksreesaila/fh-matui/blob/master/fh_matui/web_pages.py#L73"
target="_blank" style="float:right; font-size:smaller">source</a>

### HeroSection

``` python

def HeroSection(
    title:str, # Main hero title
    subtitle:str, # Hero subtitle/description
    primary_cta_text:str, # Primary CTA button text
    primary_cta_href:str, # Primary CTA button href
    secondary_cta_text:str=None, # Secondary CTA button text (optional)
    secondary_cta_href:str=None, # Secondary CTA button href (optional)
    background:str='primary-container', # BeerCSS background class (without bg- prefix)
    cls:str='', # Additional classes
    extra_css:str | None=None, # Optional custom CSS (minimal; opt-in)
    extra_js:str | None=None, # Optional custom JS (minimal; opt-in)
):

```

*Hero section with title, subtitle, and CTA buttons.*

BeerCSS-first styling. Takes up 75vh by default with gradient overlay.
Designed for full-width layout - background extends edge-to-edge
naturally. Content is centered using responsive class internally.
Mobile-friendly: title scales down via clamp(), text stays centered.

<details class="code-fold">
<summary>Code</summary>

``` python
def hero_section():
    return HeroSection(
    title="Welcome to Material UI",
    subtitle="Build beautiful web apps with FastHTML",
    primary_cta_text="Get Started",
    primary_cta_href="/signup",
    secondary_cta_text="Learn More",
    secondary_cta_href="/docs"
) 

preview(hero_section())
```

</details>

<iframe src="http://localhost:7020/_r9AfAm7ARV__C06bJKFAjw" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 

## ✨ Features Grid

<table>
<colgroup>
<col style="width: 55%" />
<col style="width: 45%" />
</colgroup>
<thead>
<tr>
<th>Component</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#featuresgrid"><code>FeaturesGrid</code></a></td>
<td>Bento-style responsive grid of feature cards with icons</td>
</tr>
</tbody>
</table>

**Features:** Configurable card sizes (`size: 'big'`/`'small'`), BeerCSS
12-column grid, mobile-responsive

## 🎯 Feature Showcase

<table>
<colgroup>
<col style="width: 55%" />
<col style="width: 45%" />
</colgroup>
<thead>
<tr>
<th>Component</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#featureshowcase"><code>FeatureShowcase</code></a></td>
<td>Bento-box image-on-top cards for detailed feature highlights</td>
</tr>
</tbody>
</table>

### Configuration Options

**Section-level parameters:**

<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>features</code></td>
<td>list</td>
<td>required</td>
<td>List of feature dicts (see below)</td>
</tr>
<tr>
<td><code>title</code></td>
<td>str</td>
<td>None</td>
<td>Section heading</td>
</tr>
<tr>
<td><code>subtitle</code></td>
<td>str</td>
<td>None</td>
<td>Section subheading</td>
</tr>
</tbody>
</table>

**Per-feature dict keys:**

<table>
<colgroup>
<col style="width: 17%" />
<col style="width: 35%" />
<col style="width: 46%" />
</colgroup>
<thead>
<tr>
<th>Key</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>title</code></td>
<td>✓</td>
<td>Feature title</td>
</tr>
<tr>
<td><code>description</code></td>
<td>✓</td>
<td>Feature description</td>
</tr>
<tr>
<td><code>image_src</code></td>
<td></td>
<td>Custom image URL/path (auto-generates placeholder if omitted)</td>
</tr>
<tr>
<td><code>image_alt</code></td>
<td></td>
<td>Alt text for image (defaults to title)</td>
</tr>
<tr>
<td><code>size</code></td>
<td></td>
<td><code>'big'</code> (l6) or <code>'small'</code> (l4) — auto-assigned
if omitted (first 2 big, rest small)</td>
</tr>
</tbody>
</table>

**Bento layout:** - First 2 features → `big` (half-width on desktop,
l6) - Remaining features → `small` (third-width on desktop, l4) - All
stack full-width on mobile (s12), 2-col on tablet (m6) - Override
per-feature with `size` key

------------------------------------------------------------------------

<a
href="https://github.com/abhisheksreesaila/fh-matui/blob/master/fh_matui/web_pages.py#L158"
target="_blank" style="float:right; font-size:smaller">source</a>

### FeatureShowcase

``` python

def FeatureShowcase(
    features:list, # List of dicts: {title, description, image_src?, image_alt?, size?}
    title:str=None, # Optional section title
    subtitle:str=None, # Optional section subtitle
    cls:str=''
):

```

*Bento-box feature showcase with image-on-top cards.*

Displays features as cards with a large image on top (~75%) and text
description on the bottom (~25%). Uses a bento grid layout: first 2
features are “big” (half-width on desktop), remaining are “small”
(third-width on desktop). All stack full-width on mobile.

Each feature can override its size via the ‘size’ key: - ‘big’: spans l6
(half width on desktop) - ‘small’: spans l4 (third width on desktop) -
If omitted: first 2 default to ‘big’, rest to ‘small’

Auto-generates placeholder images from picsum.photos if no image_src
provided.

Args: features: List of feature dicts with keys: - title: Feature title
(required) - description: Feature description (required) - image_src:
URL/path to image (optional - auto-generates placeholder) - image_alt:
Alt text for image (optional, defaults to title) - size: ‘big’ or
‘small’ (optional - auto-assigned by position) title: Section heading
subtitle: Section subheading cls: Additional CSS classes

Example: FeatureShowcase( title=“Why Choose Us”, features=\[ {‘title’:
‘Fast’, ‘description’: ‘Lightning quick’}, {‘title’: ‘Secure’,
‘description’: ‘Built-in protection’}, {‘title’: ‘Scale’, ‘description’:
‘Grows with you’}, {‘title’: ‘Simple’, ‘description’: ‘Easy to use’},
{‘title’: ‘Open’, ‘description’: ‘Open source’}, \], )

<details class="code-fold">
<summary>Code</summary>

``` python
showcase_features = [
    {'title': 'Lightning Fast', 'description': 'Built for speed with optimized rendering and minimal overhead. Your pages load instantly.'},
    {'title': 'Secure by Default', 'description': 'Enterprise-grade security with automatic CSRF protection and input sanitization.'},
    {'title': 'Infinitely Scalable', 'description': 'From prototype to production, scale seamlessly without changing your code.'},
    {'title': 'Beautiful Design', 'description': 'Material Design 3 components that look polished out of the box.'},
    {'title': 'Developer First', 'description': 'Pure Python API — no JavaScript or build tools required.'},
]

def test_showcase():
    return FeatureShowcase(
        title="Built for Modern Teams",
        subtitle="Everything you need to ship faster",
        features=showcase_features,
    )

preview(test_showcase())
```

</details>

<iframe src="http://localhost:7020/_bM1r5ZCSRmODujmzho4lpQ" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 

------------------------------------------------------------------------

<a
href="https://github.com/abhisheksreesaila/fh-matui/blob/master/fh_matui/web_pages.py#L278"
target="_blank" style="float:right; font-size:smaller">source</a>

### FeaturesGrid

``` python

def FeaturesGrid(
    features:list, # List of dicts: {icon, title, description, size?}
    title:str=None, # Optional section title
    subtitle:str=None, # Optional section subtitle
    cls:str='', # Additional classes
):

```

*Bento-style feature grid using BeerCSS 12-column grid.*

Creates visual hierarchy with configurable card sizes for a modern bento
box layout. Grid auto-fills with BeerCSS responsive column classes.

Each feature dict can include a ‘size’ key: - ‘big’: spans half width
(l6) - highlighted/featured items - ‘small’ (default): spans quarter
width (l3)

Responsive behavior (BeerCSS breakpoints): - Mobile (s): full width,
stacked (s12) - Tablet (m): 2 columns (m6) - Desktop (l): 4-column bento
(l3 small, l6 big)

Example: FeaturesGrid(\[ {“icon”: “star”, “title”: “Featured”,
“description”: “…”, “size”: “big”}, {“icon”: “bolt”, “title”: “Fast”,
“description”: “…”}, {“icon”: “shield”, “title”: “Secure”,
“description”: “…”}, \])

<details class="code-fold">
<summary>Code</summary>

``` python
# Bento layout example: 2 big features + 4 small = nice visual hierarchy
sample_features = [
    {'icon': 'bolt', 'title': 'Lightning Fast', 'description': 'Optimized rendering with minimal overhead. Pages load instantly.', 'size': 'big'},
    {'icon': 'shield', 'title': 'Secure by Default', 'description': 'Enterprise-grade security with automatic CSRF protection.', 'size': 'big'},
    {'icon': 'trending_up', 'title': 'Scalable', 'description': 'Grows with your needs'},
    {'icon': 'palette', 'title': 'Beautiful', 'description': 'Material Design tokens'},
    {'icon': 'extension', 'title': 'Extensible', 'description': 'Compose with any component'},
    {'icon': 'code', 'title': 'Developer First', 'description': 'Pure Python, no JS required'},
]

@rt('/test-fg')
def test_fg():
    return FeaturesGrid(
        features=sample_features,
        title="Why Choose Us",
        subtitle="Everything you need to ship quickly",
    )

preview(test_fg())
```

</details>

<iframe src="http://localhost:7020/_x-9SDYOERWWJKxoGLHp73g" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 

## 💰 Pricing Section

<table>
<colgroup>
<col style="width: 55%" />
<col style="width: 45%" />
</colgroup>
<thead>
<tr>
<th>Component</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#pricingsection"><code>PricingSection</code></a></td>
<td>Multi-tier pricing with monthly/yearly toggle</td>
</tr>
</tbody>
</table>

**Features:** - 1-3 pricing tiers (Starter/Pro/Enterprise pattern) -
Monthly/Yearly toggle with automatic savings calculation - Green “Save
X%” chip with subtle pulse animation - Highlight flag for recommended
tier - Responsive grid layout

------------------------------------------------------------------------

<a
href="https://github.com/abhisheksreesaila/fh-matui/blob/master/fh_matui/web_pages.py#L462"
target="_blank" style="float:right; font-size:smaller">source</a>

### PricingSection

``` python

def PricingSection(
    title:str, # Section title
    plans:list, # List of plan dicts: {name, monthly_price, yearly_price, features, cta_text, cta_href, highlight?}
    cls:str='', # Additional classes
):

```

*Multi-tier pricing section with monthly/yearly toggle.*

Supports 1-3 pricing tiers with automatic responsive layout. User
provides prices; component handles toggle, savings display, and grid.

Args: title: Section heading (e.g., “Simple Pricing”) plans: List of
plan dicts, each containing: - name: Plan name (e.g., “Starter”, “Pro”,
“Enterprise”) - monthly_price: Monthly price as float (e.g., 9.99) -
yearly_price: Yearly price as float (e.g., 99.99) - features: List of
feature strings - cta_text: Button text (e.g., “Get Started”) -
cta_href: Button link - highlight: Optional bool to emphasize this tier
(default False) cls: Additional CSS classes

Example: PricingSection( title=“Choose Your Plan”, plans=\[ {“name”:
“Starter”, “monthly_price”: 9.99, “yearly_price”: 99.99, “features”:
\[“5 users”, “Basic support”\], “cta_text”: “Start Free”, “cta_href”:
“/signup”}, {“name”: “Pro”, “monthly_price”: 29.99, “yearly_price”:
299.99, “features”: \[“Unlimited users”, “Priority support”\],
“cta_text”: “Get Pro”, “cta_href”: “/signup”, “highlight”: True}, \] )

<details class="code-fold">
<summary>Code</summary>

``` python
# Test with 3-tier pricing (Starter / Pro / Enterprise)
def test_pricing_3tier():
    return PricingSection(
        title="Choose Your Plan",
        plans=[
            {
                "name": "Starter",
                "monthly_price": 9.99,
                "yearly_price": 99.99,
                "features": [
                    "5 team members",
                    "Basic analytics",
                    "Email support",
                    "1GB storage",
                ],
                "cta_text": "Start Free",
                "cta_href": "/signup?plan=starter",
            },
            {
                "name": "Pro",
                "monthly_price": 29.99,
                "yearly_price": 299.99,
                "features": [
                    "Unlimited members",
                    "Advanced analytics",
                    "Priority support",
                    "10GB storage",
                    "API access",
                ],
                "cta_text": "Get Pro",
                "cta_href": "/signup?plan=pro",
                "highlight": True,
            },
            {
                "name": "Enterprise",
                "monthly_price": 99.99,
                "yearly_price": 999.99,
                "features": [
                    "Everything in Pro",
                    "Dedicated support",
                    "Custom SLA",
                    "Unlimited storage",
                    "SSO & SAML",
                ],
                "cta_text": "Contact Sales",
                "cta_href": "/contact",
            },
        ],
    )

preview(test_pricing_3tier())
```

</details>

<iframe src="http://localhost:7020/_a0_djNaxR4CrHLbM03L7Lw" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 

<details class="code-fold">
<summary>Code</summary>

``` python
# Test with single pricing card
def test_pricing_single():
    return PricingSection(
        title="Simple Pricing",
        plans=[
            {
                "name": "Professional",
                "monthly_price": 7.99,
                "yearly_price": 79.99,
                "features": [
                    "Unlimited users",
                    "24/7 priority support",
                    "Custom branding",
                    "Advanced analytics",
                    "Full API access",
                ],
                "cta_text": "Get Started",
                "cta_href": "/signup",
            },
        ],
    )

preview(test_pricing_single())
```

</details>

<iframe src="http://localhost:7020/_jdxPA-xmQgy0vQJsKzDKPw" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 

## ❓ FAQ Section

<table>
<colgroup>
<col style="width: 55%" />
<col style="width: 45%" />
</colgroup>
<thead>
<tr>
<th>Component</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#faqsection"><code>FAQSection</code></a></td>
<td>Expandable FAQ using native Details/Summary</td>
</tr>
</tbody>
</table>

**Features:** BeerCSS-first accordion, proper spacing between items

------------------------------------------------------------------------

<a
href="https://github.com/abhisheksreesaila/fh-matui/blob/master/fh_matui/web_pages.py#L555"
target="_blank" style="float:right; font-size:smaller">source</a>

### FAQSection

``` python

def FAQSection(
    title:str, faqs:list, cls:str=''
):

```

*FAQ section using FAQItem from components.*

Wraps multiple FAQItem components with a title and consistent spacing.
Uses FAQItem from fh_matui.components for the actual collapsible Q&A.

Args: title: Section heading faqs: List of dicts with ‘question’ and
‘answer’ keys cls: Additional CSS classes

<details class="code-fold">
<summary>Code</summary>

``` python
faqs = [
    {'question': 'What is FastHTML?', 'answer': 'FastHTML is a modern web framework'},
    {'question': 'How much does it cost?', 'answer': 'See our pricing page for details'}
]

def faq_section():
    return  FAQSection(
    title="Frequently Asked Questions",
    faqs=faqs
)

preview(faq_section())
```

</details>

<iframe src="http://localhost:7020/_S3kTH0b0SoWbcyJCxLMipw" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 

## 🦶 Footer

<table>
<colgroup>
<col style="width: 55%" />
<col style="width: 45%" />
</colgroup>
<thead>
<tr>
<th>Component</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#pagefooter"><code>PageFooter</code></a></td>
<td>Multi-column footer with social links, copyright, and decorative
wave border</td>
</tr>
<tr>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#landingnavbar"><code>LandingNavBar</code></a></td>
<td>Sticky navbar with brand, links, and CTA actions</td>
</tr>
</tbody>
</table>

**Features:** - Flexible column layout with social icon links -
Decorative sine wave border at top (`wave_border=True` by default) -
Blends seamlessly with page background

------------------------------------------------------------------------

<a
href="https://github.com/abhisheksreesaila/fh-matui/blob/master/fh_matui/web_pages.py#L608"
target="_blank" style="float:right; font-size:smaller">source</a>

### PageFooter

``` python

def PageFooter(
    columns:list, # List of dicts with 'title' and 'links' (list of dicts with 'text' and 'href')
    copyright:str, # Copyright text
    social_links:list=None, # List of dicts with 'icon' and 'href'
    logo:str=None, # Optional logo text
    wave_border:bool=True, # Show decorative wave border at top
    cls:str='', # Additional classes
):

```

*Footer with multiple columns, social links, and copyright.*

Features a decorative sine wave border at the top for elegant visual
separation. Blends with page background (no container fill) for seamless
appearance.

Mobile-responsive: columns stack vertically on mobile (s12), 2-col on
tablet (m6), full row on desktop using BeerCSS grid.

<details class="code-fold">
<summary>Code</summary>

``` python
def ex_footer():
    return   PageFooter(
    columns=[
        {'title': 'Product', 'links': [{'text': 'Features', 'href': '#features'}]},
        {'title': 'Company', 'links': [{'text': 'About', 'href': '/about'}]}
    ],
    copyright="© 2025 MyBrand",
    social_links=[{'icon': 'twitter', 'href': 'https://twitter.com'}],
    logo="MyBrand"
)

preview(ex_footer())
```

</details>

<iframe src="http://localhost:7020/_TjoFrmEJSm6UzSTV3doXxQ" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 

------------------------------------------------------------------------

<a
href="https://github.com/abhisheksreesaila/fh-matui/blob/master/fh_matui/web_pages.py#L700"
target="_blank" style="float:right; font-size:smaller">source</a>

### LandingNavBar

``` python

def LandingNavBar(
    brand_name:str, # Brand name for the navbar
    links:list=None, # List of dicts with 'text' and 'href'
    actions:list=None, # List of action buttons (Buttons/Links)
    sticky:bool=True, # Whether navbar sticks to top
    drawer_id:str='landing-nav-drawer', # ID for mobile drawer
    cls:str='', # Additional classes
):

```

*Landing page navigation bar with frosted glass effect and mobile
drawer.*

Desktop (\>=600px): horizontal bar with brand, links, and action
buttons. Mobile (\<600px): brand + hamburger button opens a slide-in
drawer via BeerCSS data-ui toggle (zero custom JavaScript).

Reuses NavContainer from components for the mobile drawer — same dialog
pattern used in app navigation sidebars.

Args: brand_name: Brand name/logo text links: Navigation links
\[{‘text’: ‘Features’, ‘href’: ‘\#features’}, …\] actions: Action
elements (Buttons, etc.) for CTA sticky: Whether navbar sticks to top
while scrolling (default: True) drawer_id: HTML id for the mobile drawer
dialog (default: ‘landing-nav-drawer’) cls: Additional CSS classes

## 📄 Landing Page

<table>
<thead>
<tr>
<th>Component</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>LandingPage</code></td>
<td>Complete landing page composition</td>
</tr>
<tr>
<td><code>LandingPageV2</code></td>
<td>Alternative landing page layout</td>
</tr>
</tbody>
</table>

**Features:** Combines Hero, Features, Pricing, FAQ, and Footer into one
component

------------------------------------------------------------------------

<a
href="https://github.com/abhisheksreesaila/fh-matui/blob/master/fh_matui/web_pages.py#L863"
target="_blank" style="float:right; font-size:smaller">source</a>

### LandingPageSimple

``` python

def LandingPageSimple(
    brand_name:str, # Required
    hero_title:str, hero_subtitle:str, hero_primary_cta:dict, # {'text': 'Get Started', 'href': '/signup'}
    footer_copyright:str, # Required copyright text
    hero_secondary_cta:dict=None, # Optional secondary CTA
    benefits:list=None, # List of dicts: {title, description, icon?, image_src?}
    benefits_title:str=None, benefits_subtitle:str=None,
    features:list=None, # List of dicts: {icon, title, description}
    features_title:str=None, features_subtitle:str=None,
    pricing_plans:list=None, # List of plan dicts for PricingSection
    pricing_title:str='Pricing', faqs:list=None, # List of FAQ dicts
    faq_title:str='Frequently Asked Questions', footer_columns:list=None, # Optional Footer extras
    footer_social_links:list=None, nav_links:list=None, # Override default nav links
    nav_actions:list=None, # CTA buttons in navbar
    cls:str=''
):

```

*Landing page component - supply your content, get a complete page.*

This is a reusable template component. Pass your brand info, hero
content, features, pricing, and FAQs - it assembles a complete marketing
landing page.

Includes smooth scrolling and proper anchor offset to prevent sticky
navbar from hiding section headings when navigating via anchor links.

Layout approach: Main uses “max” for full-width backgrounds. Each
section handles its own content centering with “responsive” wrapper.
This allows gradients/backgrounds to extend edge-to-edge naturally.

Section order: Hero → Benefits → Features → Pricing → FAQ → Footer

Required: brand_name, hero_title, hero_subtitle, hero_primary_cta,
footer_copyright Optional: Benefits, Features, Pricing, FAQ (pass None
to skip any section)

<details class="code-fold">
<summary>Code</summary>

``` python
@rt('/test-lp')
def test_landing_page():
    return LandingPageSimple(
        brand_name="FastHTML",
        hero_title="Build faster with FastHTML",
        hero_subtitle="Compose production-ready pages with Material-inspired components wired for HTMX.",
        hero_primary_cta={'text': 'Get Started', 'href': '/signup'},
        hero_secondary_cta={'text': 'View Docs', 'href': '/docs'},
        footer_copyright="© 2026 FastHTML",
        # Benefits (bento showcase) - 2 big + 3 small cards with image on top
        benefits=[
            {'title': 'Lightning Fast', 'description': 'Built for speed with optimized rendering and minimal overhead.'},
            {'title': 'Secure by Default', 'description': 'Enterprise-grade security with automatic CSRF protection.'},
            {'title': 'Infinitely Scalable', 'description': 'From prototype to production, scale seamlessly.'},
            {'title': 'Beautiful Design', 'description': 'Material Design 3 components that look polished out of the box.'},
            {'title': 'Developer First', 'description': 'Pure Python API — no JavaScript or build tools required.'},
        ],
        benefits_title="Why FastHTML?",
        benefits_subtitle="Built for modern teams",
        # Features (bento grid) - first 2 are big, rest small
        features=[
            {"icon": "dashboard", "title": "Page primitives", "description": "Hero, feature, pricing sections ready to use.", "size": "big"},
            {"icon": "bolt", "title": "HTMX ready", "description": "Live previews in notebook with zero config.", "size": "big"},
            {"icon": "palette", "title": "Color tokens", "description": "Material container classes."},
            {"icon": "extension", "title": "Composable", "description": "Extend with extra classes."},
            {"icon": "security", "title": "Accessible", "description": "WCAG friendly defaults."},
            {"icon": "rocket_launch", "title": "Fast iteration", "description": "nbdev keeps code and docs together."},
        ],
        features_title="Everything you need",
        features_subtitle="Mix heroes, features, pricing, and FAQs.",
        # Pricing
        pricing_title="Simple Pricing",
        pricing_plans=[
            {"name": "Starter", "monthly_price": 9.99, "yearly_price": 99.99,
             "features": ["5 users", "Basic support"], "cta_text": "Start Free", "cta_href": "/signup"},
            {"name": "Pro", "monthly_price": 29.99, "yearly_price": 299.99,
             "features": ["Unlimited users", "Priority support", "API access"], 
             "cta_text": "Get Pro", "cta_href": "/signup", "highlight": True},
        ],
        # FAQ
        faqs=[
            {"question": "Can I mix components?", "answer": "Yes. Every helper returns plain FastHTML nodes."},
            {"question": "How do colors work?", "answer": "Apply Material container classes to any wrapper."},
            {"question": "Is HTMX required?", "answer": "No. Interactions degrade gracefully."},
        ],
        # Footer uses STANDARD_FOOTER_COLUMNS by default (omit footer_columns to use standard)
        footer_social_links=[{"icon": "code", "href": "https://github.com"}],
    )

preview(test_landing_page())
```

</details>

<iframe src="http://localhost:7020/_TkLC52-lQqazM56ekt8s8Q" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 

## 📝 Content Pages

<table>
<colgroup>
<col style="width: 55%" />
<col style="width: 45%" />
</colgroup>
<thead>
<tr>
<th>Component</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#markdownsection"><code>MarkdownSection</code></a></td>
<td>Renders markdown text as HTML (server-side, SEO-friendly)</td>
</tr>
<tr>
<td><a
href="https://abhisheksreesaila.github.io/fh-matui/web_pages.html#contentpage"><code>ContentPage</code></a></td>
<td>Generic page shell with navbar, content area, and footer</td>
</tr>
</tbody>
</table>

**Use Cases:** Privacy Policy, Terms of Service, Security, About, Cookie
Policy, Disclaimers, Blog posts, etc.

------------------------------------------------------------------------

<a
href="https://github.com/abhisheksreesaila/fh-matui/blob/master/fh_matui/web_pages.py#L1001"
target="_blank" style="float:right; font-size:smaller">source</a>

### MarkdownSection

``` python

def MarkdownSection(
    content:str, # Markdown text to render
    title:str=None, # Optional section title (rendered as H3 for appropriate size)
    cls:str='', # Additional classes
):

```

*Renders markdown content server-side for SEO compatibility.*

    Uses python-markdown to convert markdown to HTML on the server.
    Search engines see fully rendered HTML (no JavaScript required).
    Content is centered using BeerCSS large-width + row center-align pattern.

    Great for text-heavy pages like Privacy Policy, Terms, About, Blog posts, etc.

    Args:
        content: Markdown text string (can include headers, lists, links, code blocks, tables)
        title: Optional page title (rendered as H3 for blog-appropriate sizing)
        cls: Additional CSS classes

    Example:
        MarkdownSection(
            title="Privacy Policy",
            content='''

## Introduction

We value your privacy…

## Data Collection

- We collect minimal data
- We never sell your data ’’’ )

------------------------------------------------------------------------

<a
href="https://github.com/abhisheksreesaila/fh-matui/blob/master/fh_matui/web_pages.py#L1064"
target="_blank" style="float:right; font-size:smaller">source</a>

### ContentPage

``` python

def ContentPage(
    brand_name:str, # Brand name for navbar
    footer_copyright:str, # Copyright text for footer
    sections:VAR_POSITIONAL, # Content sections (MarkdownSection, custom Divs, etc.)
    nav_links:list=None, # Override default nav links
    nav_actions:list=None, # CTA buttons in navbar
    footer_columns:list=None, # Footer link columns (uses STANDARD_FOOTER_COLUMNS by default)
    footer_social_links:list=None, # Footer social icons
    cls:str=''
):

```

*Generic content page with navbar, flexible content area, and footer.*

A shell template for text-heavy pages like Privacy Policy, Terms of
Service, Security, About, Blog posts, etc. Developer passes any number
of content sections.

Layout: Navbar (sticky) -\> Content sections (centered with
‘responsive’) -\> Footer

Uses STANDARD_FOOTER_COLUMNS by default for consistent footer across all
pages.

Args: brand_name: Brand name for navbar footer_copyright: Copyright text
\*sections: One or more content sections (MarkdownSection, custom Divs,
etc.) nav_links: Navigation links \[{‘text’: ‘Home’, ‘href’: ‘/’}, …\]
nav_actions: Action buttons for navbar footer_columns: Footer link
columns (defaults to STANDARD_FOOTER_COLUMNS) footer_social_links:
Social media icons for footer cls: Additional CSS classes

Example: ContentPage( brand_name=“MyBrand”, footer_copyright=“2026
MyBrand”, MarkdownSection(title=“Privacy Policy”, content=“…markdown…”),
nav_links=\[{‘text’: ‘Home’, ‘href’: ‘/’}\], )

<details class="code-fold">
<summary>Code</summary>

``` python
# Example: Privacy Policy page
privacy_md = '''
#### 📋 Introduction

This Privacy Policy explains how we collect, use, and protect your personal information when you use our services.

#### 📊 Information We Collect

We may collect the following types of information:

- **Account Information**: Name, email address, and password when you create an account
- **Usage Data**: How you interact with our services, including pages visited and features used
- **Device Information**: Browser type, operating system, and IP address

#### 🎯 How We Use Your Information

We use your information to:

1. Provide and improve our services
2. Communicate with you about updates and offers
3. Ensure security and prevent fraud

## 🗄️ Data Retention

We retain your data only as long as necessary to provide our services or as required by law.

#### ✅ Your Rights

You have the right to:

- Access your personal data
- Request correction of inaccurate data
- Request deletion of your data
- Opt out of marketing communications

#### 📬 Contact Us

If you have questions about this Privacy Policy, please contact us at privacy@example.com.

*Last updated: January 2026*
'''

@rt('/privacy')
def privacy_page():
    return ContentPage(
        "FastHTML",           # brand_name
        "© 2026 FastHTML",    # footer_copyright
        MarkdownSection(title="Privacy Policy", content=privacy_md),
        # Uses STANDARD_FOOTER_COLUMNS by default
    )

preview(privacy_page())
```

</details>

<iframe src="http://localhost:7020/_LzkWOTAWQ6a4YxC4v8SJuw" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 

<details class="code-fold">
<summary>Code</summary>

``` python
# Example: Security page
security_md = '''
#### 🛡️ Our Commitment to Security

We take the security of your data seriously. Here is how we protect your information:

#### 🔐 Encryption

- All data is encrypted in transit using TLS 1.3
- Sensitive data is encrypted at rest using AES-256
- Passwords are hashed using bcrypt with salt

#### 🏗️ Infrastructure

- Hosted on SOC 2 Type II certified infrastructure
- Regular security audits and penetration testing
- 24/7 monitoring and incident response

#### 🔑 Access Control

- Role-based access control (RBAC) for all systems
- Multi-factor authentication required for all employees
- Principle of least privilege enforced

#### 📜 Compliance

We comply with:

- GDPR (General Data Protection Regulation)
- CCPA (California Consumer Privacy Act)
- SOC 2 Type II

#### 🚨 Reporting Security Issues

If you discover a security vulnerability, please report it to security@example.com. We appreciate responsible disclosure.
'''

@rt('/security')
def security_page():
    return ContentPage(
        "FastHTML",           # brand_name
        "© 2026 FastHTML",    # footer_copyright
        MarkdownSection(title="Security", content=security_md),
        # Uses STANDARD_FOOTER_COLUMNS by default
    )

preview(security_page())
```

</details>

<iframe src="http://localhost:7020/_-lK0u5WMQT_k5eWjLiggsA" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 

<details class="code-fold">
<summary>Code</summary>

``` python
# Example: About Us page
about_md = '''
## 👋 Who We Are

FastHTML is built by a passionate team of developers who believe building web apps should be **fast, fun, and frustration-free**.

#### 🎯 Our Mission

To empower developers to ship beautiful, production-ready web applications in record time — without sacrificing quality or maintainability.

#### 💡 Our Story

We started FastHTML because we were tired of:

- Wrestling with complex frontend build systems
- Writing the same boilerplate code over and over
- Choosing between speed and quality

So we built a better way. FastHTML combines the best of Python, HTMX, and Material Design into a cohesive framework that just works.

#### 🌟 Our Values

- **Simplicity First**: If it's complicated, we're doing it wrong
- **Developer Experience**: Your time is precious — we respect it
- **Open Source**: Built in the open, for everyone

#### 🤝 Join Us

We're always looking for contributors and collaborators. Check out our GitHub or reach out at hello@example.com.

*Building the future of web development, one component at a time.*
'''

@rt('/about')
def about_page():
    return ContentPage(
        "FastHTML",           # brand_name
        "© 2026 FastHTML",    # footer_copyright
        MarkdownSection(title="About Us", content=about_md),
        # Uses STANDARD_FOOTER_COLUMNS by default
    )

preview(about_page())
```

</details>

<iframe src="http://localhost:7020/_EBeY8teHQVa5PHsaTXwtng" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 

<details class="code-fold">
<summary>Code</summary>

``` python
# Example: Terms of Service page
terms_md = '''
#### 📜 Terms of Service

*Effective Date: January 2026*

Please read these Terms of Service carefully before using our services.

#### ✅ Acceptance of Terms

By accessing or using FastHTML, you agree to be bound by these Terms. If you disagree with any part, you may not access the service.

#### 🔐 Account Responsibilities

When you create an account, you must:

- Provide accurate and complete information
- Maintain the security of your password
- Notify us immediately of any unauthorized access
- Accept responsibility for all activities under your account

#### 💳 Payment Terms

For paid plans:

- Billing occurs monthly or annually based on your selection
- Refunds are available within 30 days of initial purchase
- We reserve the right to change pricing with 30 days notice

#### 🚫 Prohibited Uses

You may not use our service to:

1. Violate any laws or regulations
2. Infringe on intellectual property rights
3. Distribute malware or harmful code
4. Attempt to gain unauthorized access to our systems

#### ⚖️ Limitation of Liability

FastHTML is provided "as is" without warranties of any kind. We are not liable for any indirect, incidental, or consequential damages.

#### 📝 Changes to Terms

We may modify these terms at any time. Continued use of the service constitutes acceptance of modified terms.

#### 📧 Contact

Questions about these Terms? Contact us at legal@example.com.
'''

@rt('/terms')
def terms_page():
    return ContentPage(
        "FastHTML",           # brand_name
        "© 2026 FastHTML",    # footer_copyright
        MarkdownSection(title="Terms of Service", content=terms_md),
        # Uses STANDARD_FOOTER_COLUMNS by default
    )

preview(terms_page())
```

</details>

<iframe src="http://localhost:7020/_etNFdKftQ6i8xQHDdlGukQ" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
