⚡Framework Integration

Integrating MeshBase with Next.js

Build lightning-fast Next.js applications powered by MeshBase. Server Components, App Router, SSR, SSG—all the patterns you need.

Why MeshBase + Next.js?

⚡Server Components Ready

Fetch content server-side with Next.js 13+ App Router. Fast initial loads, SEO-friendly out of the box.

🎯ISR & SSG Support

Static generation with revalidation. Build fast sites that stay fresh with incremental updates.

🚀API Routes Compatible

Use MeshBase from Next.js API routes for server-side operations, webhooks, and custom logic.

🔄Flexible Data Fetching

Server Components, Client Components, getStaticProps, getServerSideProps—MeshBase works with all patterns.

What You'll Need

  • ✓Next.js 13+ project (App Router or Pages Router)
  • ✓A MeshBase account with content types defined
  • ✓Your MeshBase API key (from Project Settings)

Quick Start: App Router (Next.js 13+)

Using the new App Router? Server Components make MeshBase integration dead simple.

1. Add your API key

Create .env.local:

MESHBASE_API_URL=https://api.meshbase.io/v1
MESHBASE_API_KEY=your-api-key-here

2. Create a data fetcher

Create lib/meshbase.ts:

const API_URL = process.env.MESHBASE_API_URL;
const API_KEY = process.env.MESHBASE_API_KEY;

export async function fetchFromMeshBase(endpoint: string) {
  const res = await fetch(`${API_URL}${endpoint}`, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    next: { revalidate: 60 } // ISR: revalidate every 60s
  });

  if (!res.ok) throw new Error('Failed to fetch from MeshBase');
  return res.json();
}

// Typed helper for blog posts
export async function getBlogPosts() {
  const { data } = await fetchFromMeshBase('/blog-posts');
  return data;
}

export async function getBlogPost(id: string) {
  const data = await fetchFromMeshBase(`/blog-posts/${id}`);
  return data;
}

3. Use in Server Components

Create app/blog/page.tsx:

import { getBlogPosts } from '@/lib/meshbase';

export default async function BlogPage() {
  const posts = await getBlogPosts();

  return (
    <div>
      <h1>Blog</h1>
      <div className="grid gap-6">
        {posts.map((post) => (
          <article key={post.id}>
            <h2>{post.title}</h2>
            <p>{post.excerpt}</p>
            <a href={`/blog/${post.id}`}>Read more</a>
          </article>
        ))}
      </div>
    </div>
  );
}
✨

That's It!

Your Next.js app now fetches content from MeshBase server-side. Fast initial loads, SEO-friendly, and automatically revalidated every 60 seconds.

Dynamic Routes

Build dynamic blog post pages with static generation.

Create app/blog/[id]/page.tsx:

import { getBlogPost, getBlogPosts } from '@/lib/meshbase';

// Generate static paths at build time
export async function generateStaticParams() {
  const posts = await getBlogPosts();
  return posts.map((post) => ({ id: post.id }));
}

export default async function BlogPostPage({ 
  params 
}: { 
  params: { id: string } 
}) {
  const post = await getBlogPost(params.id);

  return (
    <article>
      <h1>{post.title}</h1>
      {post.coverImage && (
        <img src={post.coverImage} alt={post.title} />
      )}
      <div dangerouslySetInnerHTML={{ __html: post.content }} />
    </article>
  );
}
💡

Static Generation with ISR

This pattern generates static HTML at build time, then revalidates periodically. You get static site performance with dynamic content updates!

Pages Router (Next.js 12 and earlier)

Using the Pages Router? Here's the equivalent pattern.

Static Generation with getStaticProps

// pages/blog/index.tsx
import { getBlogPosts } from '@/lib/meshbase';

export async function getStaticProps() {
  const posts = await getBlogPosts();
  
  return {
    props: { posts },
    revalidate: 60 // ISR: revalidate every 60s
  };
}

export default function BlogPage({ posts }) {
  return (
    <div>
      <h1>Blog</h1>
      {posts.map((post) => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.excerpt}</p>
        </article>
      ))}
    </div>
  );
}

Server-Side Rendering with getServerSideProps

// For real-time data (no caching)
export async function getServerSideProps() {
  const posts = await getBlogPosts();
  
  return {
    props: { posts }
  };
}

Client-Side Data Fetching

Need to fetch data client-side? Use SWR or React Query.

Using SWR (Recommended)

Install: npm install swr

'use client';
import useSWR from 'swr';

const fetcher = (url: string) => 
  fetch(url, {
    headers: {
      'Authorization': `Bearer ${process.env.NEXT_PUBLIC_MESHBASE_KEY}`
    }
  }).then(r => r.json());

export function BlogList() {
  const { data, error, isLoading } = useSWR(
    'https://api.meshbase.io/v1/blog-posts',
    fetcher
  );

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Failed to load</div>;

  return (
    <div>
      {data.data.map((post) => (
        <article key={post.id}>
          <h2>{post.title}</h2>
        </article>
      ))}
    </div>
  );
}
🔒

Client vs Server API Keys

Use NEXT_PUBLIC_MESHBASE_KEY for client-side fetching. This should be your public read-only key, not your admin key!

Advanced Patterns

On-Demand Revalidation

Revalidate content when it changes in MeshBase using webhooks:

// app/api/revalidate/route.ts
import { revalidatePath } from 'next/cache';
import { NextRequest } from 'next/server';

export async function POST(request: NextRequest) {
  const secret = request.nextUrl.searchParams.get('secret');
  
  // Verify webhook secret
  if (secret !== process.env.REVALIDATE_SECRET) {
    return Response.json({ error: 'Invalid token' }, { status: 401 });
  }

  const body = await request.json();
  
  // Revalidate the blog list
  revalidatePath('/blog');
  
  // Revalidate specific post
  if (body.id) {
    revalidatePath(`/blog/${body.id}`);
  }

  return Response.json({ revalidated: true });
}

Parallel Data Fetching

// Fetch multiple collections in parallel
export default async function HomePage() {
  const [posts, products] = await Promise.all([
    getBlogPosts(),
    getProducts()
  ]);

  return (
    <div>
      <BlogSection posts={posts} />
      <ProductSection products={products} />
    </div>
  );
}

Next Steps