AbsoluteJS

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.

TS
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:

TS
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.

TS
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:

TS
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.

TS
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:

srcpath to the source image (required)
altalternative text for accessibility (required)
widthintrinsic width in pixels. Required unless fill is set.
heightintrinsic height in pixels. Required unless fill is set.
fillwhen true, the image fills its parent container using absolute positioning
qualityoutput quality from 1 to 100
sizesresponsive sizes attribute for the browser
prioritypreload the image and disable lazy loading
placeholderplaceholder strategy while loading
blurDataURLbase64 data URL for blur placeholder
loading"lazy" or "eager". Defaults to "lazy".
unoptimizedskip optimization and serve the original image
loadercustom function to generate the image URL
overrideSrcoverride the resolved src on the rendered <img>
fetchPriority"high", "low", or "auto"
crossOriginCORS setting for the image request
referrerPolicyreferrer policy for the image request
classNameCSS class name
styleinline styles
onLoadcallback when the image finishes loading
onErrorcallback when the image fails to load

#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:

TSX
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:

TSX
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>
);