Skip to main content

Home Page Components

The Ever Works Template ships with several home page components that handle the hero section and the main listing layout. The hero can be configured as a simple props-driven component or as a fully customizable MDX-rendered section with CTA buttons, background images, and theming.

Architecture Overview

Source Files

FilePurpose
components/hero.tsxSimple hero with badge, title, description, and background effects
components/custom-hero.tsxMDX-rendered hero with CTA buttons, theming, and URL sanitization
components/home-two/home-two-layout.tsxMain listing layout with sticky filter header
components/home-two/home-two-search-bar.tsxSearch bar integrated with FilterContext
components/ui/container.tsxResponsive container wrapper

Hero Component

A straightforward hero section that accepts a badge, title, description, and optional background effects as props.

interface HeroProps {
badgeText?: string;
title?: string | React.ReactNode;
description?: string | React.ReactNode;
className?: string;
titleClassName?: string;
descriptionClassName?: string;
showBackgroundEffects?: boolean;
children?: React.ReactNode;
}

Props:

PropTypeDefaultDescription
badgeTextstring--Small badge displayed above the title
titlestring | ReactNode--Main heading (renders as h1)
descriptionstring | ReactNode--Subtitle paragraph
showBackgroundEffectsbooleantrueAnimated gradient blob effects
classNamestring""Container classes
childrenReactNode--Content below the description

The component uses the Container component with maxWidth="7xl" for the header section. Children are rendered outside the header container to allow full-width content when using fluid layout mode.

Structure:

<section aria-label="Hero">
<Container> ← Title and description
Badge
H1 Title
Description
</Container>
<div> ← Children (full-width possible)
{children}
</div>
</section>

CustomHero Component

A server-rendered hero that accepts MDX content and transforms it into styled HTML with automatic CTA button detection, XSS-safe URL handling, and configurable theming.

interface CustomHeroProps {
content: string;
frontmatter?: CustomHeroFrontmatter;
className?: string;
showBackgroundEffects?: boolean;
children?: React.ReactNode;
}

Frontmatter Configuration

FieldTypeDefaultDescription
background_imagestring--Background image URL
theme'light' | 'dark' | 'auto''auto'Color scheme
alignment'left' | 'center' | 'right''center'Content alignment
min_heightstring'auto'Minimum section height
overlay_opacitynumber0.5Background image overlay opacity

URL Sanitization

All URLs in the hero (links, images, background images) pass through a sanitizeUrl function that enforces security rules:

URL TypeResult
Relative paths (/about)Allowed
HTTP/HTTPS URLsAllowed
Protocol-relative (//evil.com)Blocked (returns null)
javascript: schemeBlocked
data: schemeBlocked
Other protocols (mailto:, ftp:)Blocked

When a URL fails validation, the element renders as a non-interactive <span> instead of an anchor tag.

Automatic CTA Button Detection

The HeroParagraph component inspects its children. If a paragraph contains only link elements (no plain text), it renders them as styled buttons instead of inline links:

PositionStyleVisual
First linkPrimary buttonFilled, theme-colored
Subsequent linksSecondary buttonOutlined, neutral

This means the following MDX:

[Get Started](/signup)
[Learn More](/docs)

Automatically renders as a primary "Get Started" button and a secondary "Learn More" button, without any special syntax.

Custom MDX Components

ElementComponentBehavior
aHeroLinkSanitized links, external opens in new tab
pHeroParagraphCTA detection for link-only paragraphs
h1HeroH1Gradient text styling
h2HeroH2Bold heading
imgHeroImagenext/image with responsive sizing

The HeroImage component uses next/image with fill layout and responsive sizes attribute for automatic optimization.

HomeTwoLayout

The main directory listing layout that combines a sticky filter header with a card grid. This is the primary listing component used across the template.

interface Home2LayoutProps {
total: number;
start: number;
page: number;
basePath: string;
categories?: Category[];
tags: Tag[];
items: ItemData[];
filteredAndSortedItems: ItemData[];
searchEnabled?: boolean;
}

Sticky Filter Header

The layout uses useStickyState (based on IntersectionObserver) to detect when the filter bar should become sticky:

StateVisual Effect
Not stickyTransparent background, no shadow
StickyWhite/dark background with blur, shadow, and border

Internal Components

The layout composes several subcomponents:

ComponentPurpose
HomeTwoFiltersCategory, tag, and sort controls
HomeTwoSearchBarSearch input using useFilters() context
ListingClientCard grid with pagination support
CardPresets.homeTwoListingDefault card configuration
ContainerResponsive width container

The ListingClient receives CardPresets.homeTwoListing merged with perPage from useLayoutTheme(), ensuring the card layout matches the user's selected theme preferences.

HomeTwoSearchBar

A search input component that connects directly to the FilterContext via useFilters().

function HomeTwoSearchBar(): JSX.Element

This component does not accept search-related props. Instead, it reads and writes the search term through the filter context, making it automatically synchronized with URL parameters and other filter controls on the page.

Customization Points

AspectHow to Customize
Hero contentEdit MDX content passed to CustomHero
Hero themeSet theme, alignment, background_image in frontmatter
Card layoutModify CardPresets.homeTwoListing or pass custom config
Items per pageControlled by useLayoutTheme().itemsPerPage
Search behaviorManaged by FilterProvider wrapping the page
Sticky thresholdAdjust rootMargin in useStickyState call

Further Reading