Configuring: MDX, Draft Mode, Security Headers, ESLint
MDX lets you write Markdown with React components inside. Great for docs and lesson content. Use @next/mdx or a content layer that compiles MDX at build time.
MDX in Next.js
MDX lets you write Markdown with React components inside. Great for docs and lesson content. Use @next/mdx or a content layer that compiles MDX at build time.
Real-life example: MDX is a recipe card that can also include a working timer widget — words plus interactive pieces on one page.
import createMDX from "@next/mdx";
const withMDX = createMDX({
extension: /\.mdx?$/,
});
const nextConfig = {
pageExtensions: ["ts", "tsx", "md", "mdx"],
};
export default withMDX(nextConfig);Draft Mode
Draft Mode lets CMS editors preview unpublished content. You enable it from a Route Handler that calls draftMode().enable(), then fetch draft data when isEnabled is true.
Real-life example: Draft Mode is a backstage pass — editors see the unfinished show; the public ticket holders wait for opening night.
// app/api/draft/route.ts
import { draftMode } from "next/headers";
import { redirect } from "next/navigation";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const secret = searchParams.get("secret");
const slug = searchParams.get("slug");
if (secret !== process.env.DRAFT_SECRET || !slug) {
return new Response("Invalid", { status: 401 });
}
const draft = await draftMode();
draft.enable();
redirect(`/blog/${slug}`);
}
// in a page:
import { draftMode } from "next/headers";
export default async function PostPage() {
const { isEnabled } = await draftMode();
const post = await getPost({ draft: isEnabled });
return <article>{/* ... */}</article>;
}Security headers, ESLint, static files
You already saw security headers in the JWT lesson — keep them in next.config for every response.
ESLint with eslint-config-next catches App Router mistakes (missing keys, bad hooks). Run next lint in CI.
Static files live in public/ and are served from /. public/logo.svg → /logo.svg. Do not put secrets there.
Real-life example: public/ is the pamphlet rack in the lobby — anyone can take a brochure; do not leave the office safe combination on that rack.
- Headers — clickjacking, MIME sniffing, referrer, permissions
- ESLint — fail CI on errors for shared repos
- public/ — images, favicons, robots manual files if needed
npx next lint
# or
npm run lint