Rendering Strategies
Understanding how different rendering approaches affect BiModal compliance
The choice of rendering strategy is the single most important architectural decision for BiModal compliance. This guide explains how Server-Side Rendering (SSR), Static Site Generation (SSG), Incremental Static Regeneration (ISR), and Client-Side Rendering (CSR) each affect your ability to meet FR-1 and serve both human and agent users effectively.
Strategy Comparison
| Strategy | FR-1 Compliance | Agent Access | Use Case |
|---|---|---|---|
| SSR | ✓ Excellent | 100% of content visible | Dynamic, personalized content |
| SSG | ✓ Excellent | 100% of content visible | Static content, documentation |
| ISR | ✓ Excellent | 100% of content visible | Semi-static content with updates |
| CSR | ✗ Non-Compliant | 0-20% of content visible | Requires mitigation strategies |
Server-Side Rendering (SSR)
Recommended Strategy
SSR is the gold standard for BiModal compliance. It renders HTML on the server for each request, ensuring all content exists in the initial HTTP response.
How SSR Works
- Browser/agent requests a page
- Server fetches data and renders complete HTML
- Fully-formed HTML is sent in the response
- Browser hydrates (adds interactivity)
- Agents read the complete content immediately
Benefits
- ✓100% agent accessible
- ✓Excellent for SEO
- ✓Fast initial page load
- ✓Real-time personalization
- ✓No JavaScript required to view
Considerations
- ⚠Requires server infrastructure
- ⚠Higher server costs at scale
- ⚠Slightly slower navigation
// app/products/[id]/page.tsx
export default async function ProductPage({ params }: { params: { id: string } }) {
// Data fetched on the server for each request
const product = await fetchProduct(params.id);
return (
<article itemScope itemType="https://schema.org/Product">
<h1 itemProp="name">{product.name}</h1>
<img
src={product.image}
alt={product.name}
itemProp="image"
/>
<div itemProp="description">
{product.description}
</div>
<span itemProp="price">{product.price}</span>
{/* Interactive button - works after hydration */}
<button onClick={() => addToCart(product.id)}>
Add to Cart
</button>
</article>
);
}Static Site Generation (SSG)
Excellent for Static Content
SSG pre-renders pages at build time, creating static HTML files. Perfect for content that doesn't change frequently.
How SSG Works
- Pages are built once during deployment
- Static HTML files are generated and stored
- Each request serves the pre-built HTML
- Content is immediately available to all users
- No server-side processing per request
Benefits
- ✓100% agent accessible
- ✓Maximum performance
- ✓Excellent SEO
- ✓Can be served from CDN
- ✓Very low hosting costs
Best For
- •Documentation sites
- •Blogs and marketing pages
- •Product catalogs (with ISR)
- •Portfolio sites
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await getAllBlogPosts();
return posts.map((post) => ({
slug: post.slug,
}));
}
export default async function BlogPost({ params }: { params: { slug: string } }) {
const post = await getPost(params.slug);
return (
<article itemScope itemType="https://schema.org/BlogPosting">
<h1 itemProp="headline">{post.title}</h1>
<time itemProp="datePublished" dateTime={post.date}>
{formatDate(post.date)}
</time>
<div itemProp="author" itemScope itemType="https://schema.org/Person">
<span itemProp="name">{post.author}</span>
</div>
<div itemProp="articleBody" dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}Incremental Static Regeneration (ISR)
Best of Both Worlds
ISR combines the performance of SSG with the freshness of SSR. Pages are statically generated but can be updated in the background.
How ISR Works
- Initial pages built at deployment (like SSG)
- Subsequent requests serve cached static HTML
- After a specified time, page is regenerated in background
- New version replaces old cached version
- Always serves full HTML - never requires JavaScript
// app/products/[id]/page.tsx
export const revalidate = 3600; // Revalidate every hour
export async function generateStaticParams() {
const products = await getTopProducts();
return products.map((product) => ({
id: product.id,
}));
}
export default async function ProductPage({ params }: { params: { id: string } }) {
const product = await fetchProduct(params.id);
return (
<article itemScope itemType="https://schema.org/Product">
<h1 itemProp="name">{product.name}</h1>
<div itemProp="offers" itemScope itemType="https://schema.org/Offer">
<span itemProp="price">{product.price}</span>
<meta itemProp="availability" content={product.inStock ? "InStock" : "OutOfStock"} />
</div>
{/* Content updates hourly but always visible to agents */}
</article>
);
}💡 Pro Tip: ISR for Product Catalogs
Use ISR for e-commerce sites where prices and inventory change regularly but don't need instant updates. Set revalidation to 1-24 hours depending on your needs.
Client-Side Rendering (CSR)
Non-Compliant Without Mitigation
Traditional CSR applications fail FR-1 because content is generated by JavaScript after the page loads. Most AI agents cannot see CSR content.
The CSR Problem
Single-page applications (SPAs) built with tools like Create React App or Vue CLI typically send an empty HTML shell and load all content via JavaScript:
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
</html>
<!-- Agents see NOTHING except this empty shell -->✗Why CSR Fails
- Empty HTML on initial load
- Content rendered by JavaScript
- Agents don't execute JavaScript
- 0-20% content visibility to agents
- Poor SEO without workarounds
→Migration Path
- Move to Next.js/Nuxt/Remix
- Enable SSR for critical pages
- Use SSG for static content
- Add API endpoint alternative
- Implement progressive enhancement
CSR Mitigation Strategies
If you must use CSR, implement one or more of these mitigation strategies:
1. Parallel API Endpoints
Provide structured API endpoints that agents can use instead of scraping HTML.
// Agents can access: /api/products/123
{
"name": "Product Name",
"description": "Full description",
"price": 29.99,
"inStock": true,
"@type": "Product",
"@context": "https://schema.org"
}2. Server-Side Rendering for Entry Points
Render landing pages, product pages, and key content with SSR while keeping interactive features in CSR.
3. Progressive Enhancement
Render basic content in HTML, then enhance with JavaScript for human users.
<!-- Basic HTML works for agents -->
<article>
<h1>Product Name</h1>
<p>Description here</p>
<a href="/checkout?id=123">Buy Now</a>
</article>
<!-- JavaScript enhances for humans -->
<script>
// Add dynamic features, animations, etc.
</script>4. Prerendering Service
Use services like Prerender.io or Rendertron to generate static snapshots for bots and agents.
Framework Recommendations
✓BiModal-Ready Frameworks
- Next.js - SSR, SSG, ISR support built-in
- Nuxt - Vue equivalent with excellent SSR
- Remix - Server-first React framework
- Astro - SSG with optional SSR
- SvelteKit - Flexible rendering options
⚠Requires Mitigation
- Create React App - Pure CSR, needs SSR migration
- Vue CLI - Pure CSR, migrate to Nuxt
- Angular - Requires Angular Universal for SSR
- Vite SPA - Pure CSR unless configured otherwise
Choosing Your Strategy
Choose SSR if you need:
- • Personalized content per user
- • Real-time data that changes frequently
- • User-specific dashboards or accounts
- • Authentication-based content
Choose SSG if you have:
- • Documentation or marketing content
- • Blog posts or articles
- • Content that rarely changes
- • Maximum performance requirements
Choose ISR if you want:
- • Performance of SSG with periodic updates
- • Product catalogs with daily/hourly changes
- • News sites with regular content updates
- • Balance between freshness and performance
⚠Only use CSR if:
- • You have a strong mitigation strategy
- • Content is not business-critical for agents
- • You provide parallel API endpoints
- • You're planning to migrate to SSR/SSG soon
Testing Your Rendering Strategy
Validate your rendering strategy with the curl test:
curl -s https://yoursite.com/page | grep -o '<[^>]*>[^<]*</[^>]*>' | head -20
# If you see meaningful content (headings, paragraphs, data):
✓ BiModal compliant
# If you see only empty divs or script tags:
✗ Non-compliant - implement mitigation strategiesNext Steps
Now that you understand rendering strategies, learn how to implement the seven Foundational Requirements that make your site truly BiModal: