This is a sample page rendered by SeoPages. Every component on this page comes from the @seopages/ui library — pure CSS, zero JavaScript, fully accessible HTML.
Server-side rendered HTML delivered from the edge. No client-side JavaScript required.
Semantic HTML with proper heading hierarchy, accessible landmarks, and crawlable content.
Override CSS custom properties to match any brand. No rebuild needed — just set your tokens.
The display uses auto-fill with a minimum column width. Items flow naturally and wrap responsively — no breakpoints needed.
The card uses the outlined variant with large padding, making it suitable for primary content areas.
Cards sit side by side when there's room, and stack when there isn't.
Default card with a subtle border. Clean and minimal.
Surface-filled card. Draws attention to featured content.
No border, transparent. Blends into the background.
Just a quick note.
This card has more content to demonstrate how masonry fills vertical gaps. Items pack tightly instead of aligning to rigid row heights.
The layout adapts naturally to varying content lengths — perfect for galleries, testimonials, or blog post grids.
Somewhere in between. The masonry layout places this card optimally to minimize whitespace.
Compact and tidy.
This card is the tallest of the bunch. In a standard grid, all items in the same row would stretch to match this height, leaving awkward gaps.
With masonry, each item takes only the vertical space it needs. The next item slots into the shortest column automatically.
No JavaScript required — pure CSS via display: grid-lanes.
Wraps up the masonry demo. Resize the browser to see columns reflow.
Just a quick note.
This card has more content to demonstrate how masonry fills vertical gaps. Items pack tightly instead of aligning to rigid row heights.
The layout adapts naturally to varying content lengths — perfect for galleries, testimonials, or blog post grids.
Somewhere in between. The masonry layout places this card optimally to minimize whitespace.
Compact and tidy.
This card is the tallest of the bunch. In a standard grid, all items in the same row would stretch to match this height, leaving awkward gaps.
With masonry, each item takes only the vertical space it needs. The next item slots into the shortest column automatically.
No JavaScript required — pure CSS via display: grid-lanes.
Wraps up the masonry demo. Resize the browser to see columns reflow.
A vibrant gradient wraps this card. The "border" is actually padding on a wrapper div with a CSS background.
Larger width and radius make the gradient border more prominent. Works with any CSS background value.
A rainbow conic gradient border — impossible with native CSS borders.
Repeating stripes as a border — any CSS background pattern works here.
A looping video plays behind the padding area, creating an animated border effect. The inner content sits above the video via z-index.
Horizontal scroll-snap with native CSS pagination dots via
::scroll-marker — zero JavaScript.
The mask fades content into transparency at the top and bottom edges.
Scroll this block to see how the gradient clips long content naturally.
No JavaScript, no overlays — pure CSS mask-image on a wrapper div.
Useful for scrollable lists, long reading content, or hinting overflow.
Works in every modern browser via the mask-image property.
Each edge fade is independent and composes with the others.
SwiftUI-style HStack / VStack / ZStack via the direction prop. Pure flexbox for horizontal/vertical, single-cell grid for depth.
Three cards share one grid cell, then per-child nth-child transforms fan them out with perspective. Hover to spread further.
Behind the stack
Front and centered
Peeking on the right
Merged buttons with zero gap — only the first and last keep their outer corners.
Left
Middle
Inline variant flows with prose. Block variant
renders a scrollable <pre><code> surface
with an optional language label. Uses --sp-font-mono
and global radius, border, and space tokens.
import { Modal, Button } from "@seopages/ui";
export function ConfirmDelete() {
return (
<Modal id="confirm" size="sm">
<Title as="h3">Delete this item?</Title>
<Text>This cannot be undone.</Text>
<ButtonGroup>
<Button href="#!" variant="outline">Cancel</Button>
<Button href="#!">Delete</Button>
</ButtonGroup>
</Modal>
);
} .sp-card {
background-color: var(--sp-color-surface);
border-radius: var(--sp-radius);
padding: var(--sp-space);
font-family: var(--sp-font-body);
} make render-dev # local Astro dev with .env.development
make render-deploy # build + push secrets + wrangler deploy A plain block without a language label, with wrap enabled — long lines break instead of scrolling horizontally. Useful for prose-adjacent snippets where horizontal overflow would be disruptive to the reading flow.
Zero-JS <dialog> driven by :target.
Open via a link to the modal's id, close via any link to
a non-matching hash (default #!). Click the backdrop or
the ✕ to dismiss.
Native <details> / <summary> —
zero JavaScript, keyboard accessible, theme tokens cascade (try the
dark-mode toggle).
SeoPages renders tenant websites from a shared component library at the edge. Every page is static HTML, cached aggressively, and invalidated on demand.
This disclosure block is a single Trigger
primitive wrapping plain text — click the summary to collapse it.
No. The Trigger uses the native <details> element. Sharing a name across siblings makes opening one close
the others — the HTML spec handles it.
Every surface, spacing, and radius value pulls from --sp-* custom properties. Flip the dark-mode
toggle in the header with a trigger open — the colors update
without remounting.
The summary is keyboard-focusable; Space and Enter toggle it.
Screen readers announce expanded/collapsed state via the
native element, and a visible focus ring uses --sp-color-primary.
Trigger holds any primitive — Cards, Displays, Stacks, even another Trigger.
The flat variant drops its border so the parent Card owns the outline.