React Components
AbsoluteJS provides Head, JsonLd, Image, StreamSlot, and SuspenseSlot components for React. Import them from @absolutejs/absolute/react/components.
#Head Component
The Head component renders meta tags, Open Graph tags, Twitter Cards, canonical URLs, and robots directives into the document <head>. It accepts a flat props object that maps directly to the underlying Metadata type.
import { Head } from '@absolutejs/absolute/react/components';
export const HomePage = () => (
<html>
<Head
title="My App"
description="A modern web application built with AbsoluteJS"
icon="/favicon.ico"
/>
<body>
<h1>Welcome</h1>
</body>
</html>
);For full control over SEO metadata, pass Open Graph, Twitter Card, and robots configuration:
import { Head } from '@absolutejs/absolute/react/components';
export const BlogPost = ({ title, excerpt, slug, coverImage }) => (
<html>
<Head
title={title}
description={excerpt}
icon="/favicon.ico"
font="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap"
cssPath={['/styles/global.css', '/styles/blog.css']}
canonical={`https://mysite.com/blog/${slug}`}
openGraph={{
title,
description: excerpt,
url: `https://mysite.com/blog/${slug}`,
image: coverImage,
imageAlt: `Cover image for ${title}`,
imageWidth: 1200,
imageHeight: 630,
type: 'article',
siteName: 'My App',
locale: 'en_US'
}}
twitter={{
card: 'summary_large_image',
title,
description: excerpt,
image: coverImage,
imageAlt: `Cover image for ${title}`,
site: '@myapp',
creator: '@author'
}}
robots={{
index: true,
follow: true,
noarchive: false,
nosnippet: false,
noimageindex: false,
maxSnippet: -1,
maxImagePreview: 'large',
maxVideoPreview: -1
}}
meta={[
{ name: 'author', content: 'Jane Doe' },
{ property: 'article:published_time', content: '2026-03-28' }
]}
/>
<body>
<article>
<h1>{title}</h1>
</article>
</body>
</html>
);#JsonLd Component
The JsonLd component renders structured data as a <script type="application/ld+json"> tag. The @context is automatically added by the component: you only need to provide the schema fields.
import { JsonLd } from '@absolutejs/absolute/react/components';
export const BlogPost = ({ title, author, datePublished, image }) => (
<html>
<head>
<title>{title}</title>
<JsonLd
schema={{
'@type': 'Article',
headline: title,
author: {
'@type': 'Person',
name: author
},
datePublished,
image
}}
/>
</head>
<body>
<article>
<h1>{title}</h1>
</article>
</body>
</html>
);Pass an array to render multiple schemas in a single JSON-LD block:
import { JsonLd } from '@absolutejs/absolute/react/components';
export const HomePage = () => (
<html>
<head>
<title>My App</title>
<JsonLd
schema={[
{
'@type': 'Organization',
name: 'My Company',
url: 'https://mysite.com',
logo: 'https://mysite.com/logo.png',
sameAs: [
'https://twitter.com/mycompany',
'https://github.com/mycompany'
]
},
{
'@type': 'WebSite',
name: 'My App',
url: 'https://mysite.com',
potentialAction: {
'@type': 'SearchAction',
target: 'https://mysite.com/search?q={search_term}',
'query-input': 'required name=search_term'
}
}
]}
/>
</head>
<body>
<h1>Welcome</h1>
</body>
</html>
);#Image Component
The Image component provides automatic responsive srcset generation, WebP/AVIF format negotiation, and on-demand image optimization through the /_absolute/image endpoint.
import { Image } from '@absolutejs/absolute/react';
// Responsive image : generates srcset for all device sizes
export const Hero = () => (
<Image
src="/images/hero.jpg"
alt="Hero banner"
width={1200}
height={600}
priority
/>
);
// Fill container : image stretches to fill its parent
export const Background = () => (
<div style={{ position: 'relative', width: '100%', height: 400 }}>
<Image
src="/images/bg.jpg"
alt="Background"
fill
style={{ objectFit: 'cover' }}
/>
</div>
);
// Fixed size with explicit dimensions
export const Avatar = ({ user }: { user: { name: string; avatar: string } }) => (
<Image
src={user.avatar}
alt={user.name}
width={48}
height={48}
quality={90}
/>
);
// Skip optimization for SVGs or already-optimized images
export const Logo = () => (
<Image
src="/images/logo.svg"
alt="Logo"
width={120}
height={40}
unoptimized
/>
);#Image Props
All available props for the Image component:
fill is set.fill is set."lazy" or "eager". Defaults to "lazy".src on the rendered <img>"high", "low", or "auto"#Priority & Preloading
Setting priority=true on an Image component adds a <link rel="preload"> tag to the document head for the image. It also sets loading="eager" and fetchPriority="high" on the rendered <img> element.
Use this for above-the-fold images like hero banners and LCP elements. Avoid setting priority on images below the fold: it wastes bandwidth and can hurt performance.
#Fill Mode
When fill is set, the image uses absolute positioning to fill its parent container. You do not need to provide width or height. The parent must have position: relative (or absolute / fixed).
Use style={{ objectFit: 'cover' }} or objectFit: 'contain' to control how the image scales within the container.
#Streaming Components
React has both layers of the out-of-order streaming model. Use StreamSlot when you want the raw transport and will provide fallback and resolved HTML yourself. Use SuspenseSlot when you want to author fallback and resolved UI directly in JSX.
These primitives are only activated when the route uses handleReactPageRequest with { collectStreamingSlots: true } in the options argument.
SuspenseSlot is the framework-native surface. It still lowers into the same slot transport underneath, so slots can resolve out of DOM order while staying in document order.
Raw transport with StreamSlot:
import { StreamSlot } from '@absolutejs/absolute/react/components';
export const Dashboard = () => (
<main>
<h1>Dashboard</h1>
<StreamSlot
id="react-activity"
fallbackHtml="<div class='card-skeleton'>Loading activity...</div>"
resolve={async () => renderActivityHtml(await getActivity())}
/>
</main>
);Framework-native transport with SuspenseSlot:
import { SuspenseSlot } from '@absolutejs/absolute/react/components';
export const Dashboard = () => (
<main>
<h1>Dashboard</h1>
<SuspenseSlot
id="react-activity"
promise={getActivity()}
fallback={<ActivitySkeleton />}
>
{({ value }) => <ActivityPanel activity={value} />}
</SuspenseSlot>
<SuspenseSlot
id="react-metrics"
promise={getMetrics()}
fallback={<MetricsSkeleton />}
>
{({ value }) => <MetricsPanel metrics={value} />}
</SuspenseSlot>
</main>
);