Test Category

Test Blog Post

Starter template for writing out a blog post using MDX/JSX and Next.js.

No Name Exists

Abdullah Muhammad

Published on August 17, 20255 min read

Article Cover Image

Understand Dynamic MDX with Supabase

MDX opens the door to combining Markdown with JSX, making your blog or documentation highly flexible. But what if you don’t want to keep your MDX files in the file system? That’s where Supabase comes in.

In this article, we explore how to store and render MDX content dynamically from Supabase, using next-mdx-remote in a Next.js App Router project.


🧠 Why Store MDX in Supabase?

Storing MDX in Supabase enables:

  • Dynamic blog posts
  • Easier authoring through a CMS or dashboard
  • Version control and user-generated content
  • Centralized content API

Instead of placing .mdx files in your repo, you fetch them from Supabase and render them as needed.


Working with Images in MDX

The following is an image utilizing the Next.js Image component and the built-in HTML element for working with figcaptions:

No Image Found
This is an image

🛠️ Storing MDX in Supabase

Create a table named articles in Supabase with columns like:

  • id: UUID
  • slug: text
  • title: text
  • content: text (your raw MDX string)
  • created_at: timestamp

Here’s a sample GitHub Gist for you to view:

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { verify } from 'jsonwebtoken';

// Simple middleware to protect specific routes
export function middleware(request: NextRequest) {
  // Get token from cookies
  const token = request.cookies.get('token')?.value;
  
  // If no token exists, direct the user to the main page.
  // Send a response redirect
  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  
  try {
    // Verify JWT
    const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
    verify(token, JWT_SECRET);
    
    // If the token is valid, transfer control of request to the appropriate route handler function
    return NextResponse.next();
  } 
  catch (error) {
    // Token is invalid, redirect to login
    return NextResponse.redirect(new URL('/login', request.url));
  }
}

// Only run middleware on protected routes
export const config = {
  matcher: ['/dashboard/:path*', '/profile/:path*', '/api/protected/:path*'],
};
Hello World!

And here, is a sample code block featuring how to work with SQL

INSERT INTO articles (id, slug, title, content) VALUES (
  uuid_generate_v4(),
  'dynamic-mdx-with-supabase',
  'Understand Dynamic MDX with Supabase',
  '# Hello from Supabase\n\nThis MDX content is stored in the cloud!',
  now()
);
No Name

Abdullah Muhammad

Blogger. Software Engineer. Designer.