skills /nextjs-mdx-design
Next.js Referenced

nextjs-mdx-design

Create beautiful Next.js 15+ documents with MDX and shadcn/ui including academic articles (Distill-inspired), data blog posts with modern styling, and interactive presentations.

Next.js MDX Design System

Create three types of beautiful, production-ready documents using Next.js 15+, MDX, and shadcn/ui:

  1. Academic Articles - Distill-inspired design with margin notes, citations, and elegant typography
  2. Data Blog Posts - Modern web design with hero sections, feature grids, and interactive elements
  3. Interactive Presentations - Slide-based presentations with keyboard navigation and transitions

When to Use This Skill

Triggers for Academic Articles:

  • "Create an academic paper/article/research document"
  • "I need a paper with citations and margin notes"
  • "Make a scientific/research publication"
  • Requests for formal academic writing with references

Triggers for Blog Posts:

  • "Create a blog post/tutorial/guide"
  • "Make a modern web article"
  • "I need a data analysis blog"
  • Requests for web-first content with modern design

Triggers for Presentations:

  • "Create a presentation/slide deck"
  • "Make slides for a talk"
  • "I need an interactive presentation"
  • Requests for slide-based content with navigation

Prerequisites

Required dependencies:

hljs bash
# Next.js and React npm install next@latest react@latest react-dom@latest # MDX support npm install @next/mdx @mdx-js/loader @mdx-js/react @mdx-js/mdx # Markdown plugins npm install remark-gfm remark-math rehype-katex rehype-pretty-code # Tailwind CSS with typography npm install -D @tailwindcss/typography # shadcn/ui (optional but recommended) npx shadcn@latest init npx shadcn@latest add button card tabs badge separator # Animation library (optional) npm install framer-motion

System requirements:

  • Node.js 18+
  • Next.js 15+
  • React 19+
  • TypeScript 5+

Bundled Resources

References (references/)

Load these when implementing specific features or needing detailed guidance:

  • quick-reference.md - Common patterns, components, and MDX syntax
  • troubleshooting.md - Common issues and solutions

Assets (assets/)

Production-ready templates for each document type:

  • academic/ - Distill-inspired academic article template

    • page.mdx - Article content template
    • layout.tsx - Academic layout with margin notes
    • components/Callout.tsx - Callout boxes
    • components/Citation.tsx - Citation components
    • components/MarginNote.tsx - Margin note component
  • blog/ - Modern blog post template

    • page.mdx - Blog content template
    • layout.tsx - Blog layout
    • components/Hero.tsx - Hero section component
    • components/FeatureGrid.tsx - Feature grid component
  • presentation/ - Interactive presentation template

    • page.mdx - Presentation content template
    • layout.tsx - Presentation layout with navigation
    • components/Slide.tsx - Slide component
    • components/TwoColumn.tsx - Two-column layout component
  • globals.css - Global styles and Tailwind configuration

Quick Start

1. Project Setup

hljs bash
# Create Next.js project with TypeScript and Tailwind npx create-next-app@latest my-project --typescript --tailwind --app cd my-project # Install MDX dependencies npm install @next/mdx @mdx-js/loader @mdx-js/react @mdx-js/mdx # Install remark/rehype plugins npm install remark-gfm remark-math rehype-katex rehype-pretty-code # Install Tailwind typography npm install -D @tailwindcss/typography # Install shadcn/ui npx shadcn@latest init npx shadcn@latest add button card tabs badge separator # Optional: Animation library npm install framer-motion

2. Configure Next.js for MDX

hljs javascript
// next.config.mjs import createMDX from '@next/mdx' import remarkGfm from 'remark-gfm' import remarkMath from 'remark-math' import rehypeKatex from 'rehype-katex' import rehypePrettyCode from 'rehype-pretty-code' /** @type {import('next').NextConfig} */ const nextConfig = { pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'], experimental: { mdxRs: true, }, } const withMDX = createMDX({ options: { remarkPlugins: [remarkGfm, remarkMath], rehypePlugins: [ rehypeKatex, [rehypePrettyCode, { theme: 'github-dark', keepBackground: false, }], ], }, }) export default withMDX(nextConfig)

3. Configure Tailwind

hljs javascript
// tailwind.config.ts import type { Config } from "tailwindcss"; const config: Config = { darkMode: ["class"], content: [ "./pages/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}", "./app/**/*.{js,ts,jsx,tsx,mdx}", ], theme: { extend: { typography: { DEFAULT: { css: { maxWidth: 'none', }, }, }, }, }, plugins: [require("@tailwindcss/typography")], }; export default config;

Document Types

1. Academic Articles (Distill-Inspired)

Design Features:

  • Narrow content column (760px max-width) with wide margins (300px)
  • Source Serif 4 typography for elegant readability
  • Margin notes positioned absolutely on desktop, inline on mobile
  • Citation system with hover tooltips
  • Callout boxes for important information
  • Article metadata (authors, affiliations, ORCID, DOI)
  • Responsive table of contents
  • LaTeX math support via KaTeX

File Structure:

app/ └── (academic)/ # Route group (URL won't include "academic") └── my-article/ └── page.mdx # Your article content

Typography:

  • Font: Source Serif 4 (serif)
  • Body: 21px / 1.58 line-height
  • Headings: Bold, carefully sized hierarchy

Components:

  • MarginNote - Side notes in margins
  • Citation - Inline citations with hover cards
  • Callout - Highlighted information boxes
  • ArticleHeader - Author/affiliation metadata
  • TableOfContents - Auto-generated from headings

2. Data Blog Posts

Design Features:

  • Modern gradient hero sections
  • Feature card grids for highlighting key points
  • shadcn/ui components (Tabs, Buttons, Cards, Badges)
  • Code syntax highlighting with rehype-pretty-code
  • Collapsible sections for long content
  • Inter typography for clean, modern look

File Structure:

app/ └── (blog)/ # Route group └── my-post/ └── page.mdx # Your blog post

Typography:

  • Font: Inter (sans-serif)
  • Body: 18px / 1.75 line-height
  • Modern, readable design

Components:

  • Hero - Gradient hero sections with CTAs
  • FeatureGrid - Card-based feature highlights
  • CodeBlock - Syntax-highlighted code
  • shadcn/ui components

3. Interactive Presentations

Design Features:

  • Full-screen slide navigation
  • Keyboard controls (arrow keys, space, f for fullscreen)
  • Slide counter and navigation UI
  • Multiple layout options (gradient, dark, light backgrounds)
  • Two-column layouts for content + visuals
  • Progressive disclosure support (with Framer Motion)

File Structure:

app/ └── (presentation)/ # Route group └── my-talk/ └── page.mdx # Your slides

Typography:

  • Font: Inter or custom presentation fonts
  • Large text sizes (3xl-7xl) for visibility
  • High contrast for readability

Components:

  • Slide - Individual slide container with ID-based navigation
  • TwoColumn - Split slide into two columns
  • Presentation navigation controls

Implementation Guide

Academic Article Setup

1. Create Layout:

hljs typescript
// app/(academic)/layout.tsx import type { Metadata } from 'next' import { Source_Serif_4 } from 'next/font/google' import '@/app/globals.css' const sourceSerif = Source_Serif_4({ subsets: ['latin'] }) export const metadata: Metadata = { title: 'Academic Articles', description: 'Research publications', } export default function AcademicLayout({ children, }: { children: React.ReactNode }) { return ( <div className={sourceSerif.className}> <main className="min-h-screen bg-white"> {children} </main> </div> ) }

2. Create MarginNote Component:

hljs typescript
// components/academic/MarginNote.tsx 'use client' interface MarginNoteProps { children: React.ReactNode number?: number } export function MarginNote({ children, number }: MarginNoteProps) { return ( <span className="margin-note-wrapper relative"> {number && ( <sup className="text-blue-600 cursor-help">{number}</sup> )} <span className="margin-note absolute left-[calc(100%+2rem)] w-[280px] text-sm text-gray-600 leading-relaxed hidden lg:block"> {children} </span> <span className="lg:hidden inline-block mt-2 px-4 py-2 bg-blue-50 text-sm text-gray-700 rounded-md border-l-4 border-blue-400"> {children} </span> </span> ) }

3. Create Citation Component:

hljs typescript
// components/academic/Citation.tsx 'use client' import { useState } from 'react' interface CitationProps { id: string children: React.ReactNode reference: string } export function Citation({ id, children, reference }: CitationProps) { const [showTooltip, setShowTooltip] = useState(false) return ( <span className="relative inline"> <span className="text-blue-600 cursor-help hover:underline" onMouseEnter={() => setShowTooltip(true)} onMouseLeave={() => setShowTooltip(false)} > {children} </span> {showTooltip && ( <span className="absolute bottom-full left-0 mb-2 w-64 p-3 bg-gray-900 text-white text-xs rounded-lg shadow-lg z-10"> {reference} </span> )} </span> ) }

4. Create Callout Component:

hljs typescript
// components/academic/Callout.tsx import { ReactNode } from 'react' interface CalloutProps { children: ReactNode type?: 'info' | 'warning' | 'success' | 'error' title?: string } export function Callout({ children, type = 'info', title }: CalloutProps) { const styles = { info: 'bg-blue-50 border-blue-200 text-blue-900', warning: 'bg-yellow-50 border-yellow-200 text-yellow-900', success: 'bg-green-50 border-green-200 text-green-900', error: 'bg-red-50 border-red-200 text-red-900', } return ( <div className={`my-6 p-4 border-l-4 rounded-r-lg ${styles[type]}`}> {title && <div className="font-bold mb-2">{title}</div>} <div className="text-sm">{children}</div> </div> ) }

5. Create Article Header:

hljs typescript
// components/academic/ArticleHeader.tsx interface Author { name: string affiliation: string orcid?: string } interface ArticleHeaderProps { title: string authors: Author[] abstract: string doi?: string date?: string } export function ArticleHeader({ title, authors, abstract, doi, date }: ArticleHeaderProps) { return ( <header className="mb-12 pb-8 border-b border-gray-200"> <h1 className="text-5xl font-bold mb-6 leading-tight">{title}</h1> <div className="mb-6 space-y-2"> {authors.map((author, idx) => ( <div key={idx} className="text-gray-700"> <span className="font-semibold">{author.name}</span> {author.orcid && ( <a href={`https://orcid.org/${author.orcid}`} className="ml-2 text-blue-600 hover:underline text-sm"> ORCID </a> )} <div className="text-sm text-gray-600">{author.affiliation}</div> </div> ))} </div> {date && <div className="text-sm text-gray-600 mb-4">{date}</div>} {doi && ( <div className="text-sm text-gray-600 mb-6"> DOI: <a href={`https://doi.org/${doi}`} className="text-blue-600 hover:underline">{doi}</a> </div> )} <div className="bg-gray-50 p-6 rounded-lg"> <h2 className="text-xl font-bold mb-3">Abstract</h2> <p className="text-gray-700 leading-relaxed">{abstract}</p> </div> </header> ) }

6. Create Example Article:

hljs mdx
// app/(academic)/my-article/page.mdx import { ArticleHeader } from '@/components/academic/ArticleHeader' import { MarginNote } from '@/components/academic/MarginNote' import { Citation } from '@/components/academic/Citation' import { Callout } from '@/components/academic/Callout' <div className="max-w-[760px] mx-auto px-6 py-12 relative"> <ArticleHeader title="The Impact of Supply Chain Disruptions on Global Trade" authors={[ { name: "John Doe", affiliation: "Economics Department, University", orcid: "0000-0000-0000-0000" }, { name: "Jane Smith", affiliation: "Business School, University" } ]} abstract="This paper examines how supply chain disruptions impact global trade patterns. We employ a triple-difference identification strategy..." doi="10.1234/example.2024" date="October 2024" /> ## Introduction The global supply chain has become increasingly complex<MarginNote>Recent studies show over 90% of Fortune 500 companies experienced supply chain disruptions in the past year.</MarginNote> and interconnected in recent decades. <Citation id="smith2023" reference="Smith, J. (2023). Supply Chain Resilience. Journal of Economics."> Previous research has documented </Citation> the vulnerability of just-in-time manufacturing systems. <Callout type="info" title="Key Finding"> Our analysis reveals a 23% increase in shipping times during disruption periods, with cascading effects throughout the supply network. </Callout> ## Methodology We employ a **shift-share triple-difference** design that leverages variation in: 1. Industry exposure to disrupted routes 2. Regional dependence on affected ports 3. Timing of disruption events The identification strategy follows: $$ y_{irt} = \alpha + \beta_1 Disruption_{rt} + \beta_2 Exposure_{ir} + \beta_3 (Disruption_{rt} \times Exposure_{ir}) + \gamma_{it} + \delta_{rt} + \epsilon_{irt} $$ <MarginNote>This specification includes industry-time and region-time fixed effects to control for confounding factors.</MarginNote> ## Data Our analysis combines: - **Port performance metrics** from Vizion (2020-2024) - **Trade flows** from UN Comtrade - **Shipping routes** from Lloyd's List Intelligence <Callout type="warning"> Data limitations: Some developing economies lack comprehensive port-level data before 2021. </Callout> ## Results Table 1 presents our main findings. The disruption effect is statistically significant (p < 0.01) and economically meaningful. | Variable | Coefficient | Std. Error | p-value | |----------|-------------|------------|---------| | Disruption × Exposure | -0.234 | 0.045 | <0.001 | | Disruption | -0.123 | 0.032 | <0.001 | | Exposure | 0.089 | 0.028 | 0.002 | <MarginNote number={1}>All standard errors are clustered at the region-industry level to account for serial correlation.</MarginNote> ## Conclusion Our findings demonstrate that supply chain disruptions have persistent effects on trade patterns, lasting well beyond the immediate disruption period. </div>

Blog Post Setup

1. Create Layout:

hljs typescript
// app/(blog)/layout.tsx import type { Metadata } from 'next' import { Inter } from 'next/font/google' import '@/app/globals.css' const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { title: 'Blog', description: 'Data analysis and insights', } export default function BlogLayout({ children, }: { children: React.ReactNode }) { return ( <div className={inter.className}> <main className="min-h-screen bg-white"> {children} </main> </div> ) }

2. Create Hero Component:

hljs typescript
// components/blog/Hero.tsx import { Button } from '@/components/ui/button' import Link from 'next/link' interface HeroProps { title: string description: string primaryAction?: { label: string href: string } secondaryAction?: { label: string href: string } } export function Hero({ title, description, primaryAction, secondaryAction }: HeroProps) { return ( <div className="relative overflow-hidden bg-gradient-to-br from-blue-600 via-purple-600 to-pink-600 text-white"> <div className="absolute inset-0 bg-black/20"></div> <div className="relative max-w-7xl mx-auto px-6 py-24 sm:py-32"> <div className="max-w-3xl"> <h1 className="text-5xl sm:text-6xl font-bold mb-6 leading-tight"> {title} </h1> <p className="text-xl sm:text-2xl mb-8 text-white/90 leading-relaxed"> {description} </p> <div className="flex flex-wrap gap-4"> {primaryAction && ( <Button asChild size="lg" className="bg-white text-purple-600 hover:bg-gray-100"> <Link href={primaryAction.href}>{primaryAction.label}</Link> </Button> )} {secondaryAction && ( <Button asChild size="lg" variant="outline" className="border-white text-white hover:bg-white/10"> <Link href={secondaryAction.href}>{secondaryAction.label}</Link> </Button> )} </div> </div> </div> </div> ) }

3. Create FeatureGrid Component:

hljs typescript
// components/blog/FeatureGrid.tsx import { Card } from '@/components/ui/card' import { ReactNode } from 'react' interface Feature { icon?: ReactNode title: string description: string } interface FeatureGridProps { features: Feature[] } export function FeatureGrid({ features }: FeatureGridProps) { return ( <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 my-12"> {features.map((feature, idx) => ( <Card key={idx} className="p-6 hover:shadow-lg transition-shadow"> {feature.icon && ( <div className="mb-4 text-blue-600"> {feature.icon} </div> )} <h3 className="text-xl font-bold mb-2">{feature.title}</h3> <p className="text-gray-600 leading-relaxed">{feature.description}</p> </Card> ))} </div> ) }

4. Create Example Blog Post:

hljs mdx
// app/(blog)/my-post/page.mdx import { Hero } from '@/components/blog/Hero' import { FeatureGrid } from '@/components/blog/FeatureGrid' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' <Hero title="Analyzing Port Performance with Modern Data Tools" description="Learn how to visualize and analyze shipping data using Observable Plot, Quarto, and Python" primaryAction={{ label: "Get Started", href: "#start" }} secondaryAction={{ label: "View Demo", href: "#demo" }} /> <div className="max-w-4xl mx-auto px-6 py-12"> <div className="flex gap-2 mb-8"> <Badge>Data Analysis</Badge> <Badge variant="secondary">Python</Badge> <Badge variant="outline">Observable Plot</Badge> </div> ## Introduction Modern supply chain analytics requires powerful visualization tools. In this guide, we'll explore how to analyze port performance metrics using cutting-edge data tools. <FeatureGrid features={[ { title: "Interactive Visualizations", description: "Create responsive charts that adapt to your data with Observable Plot" }, { title: "Reproducible Analysis", description: "Use Quarto to combine code, data, and narrative in one document" }, { title: "Python Integration", description: "Leverage pandas and pyobsplot for seamless data processing" } ]} /> ## Getting Started {#start} First, install the required packages: ```bash pip install pandas pyobsplot polars

Then import your dependencies:

hljs python
import pandas as pd import pyobsplot as op # Load port performance data df = pd.read_parquet("port_metrics.parquet")

Data Analysis

Let's analyze dwell times across different ports:

<Tabs defaultValue="code" className="my-8"> <TabsList> <TabsTrigger value="code">Code</TabsTrigger> <TabsTrigger value="output">Output</TabsTrigger> </TabsList> <TabsContent value="code"> ```python # Calculate average dwell times by port avg_dwell = df.groupby('port_name')['dwell_time'].mean() # Create visualization op.Plot.plot({ "marks": [ op.Plot.barY(avg_dwell, { "x": "port_name", "y": "dwell_time", "fill": "steelblue" }) ] }) ``` </TabsContent> <TabsContent value="output"> <div className="p-4 bg-gray-50 rounded-lg"> Chart would appear here </div> </TabsContent> </Tabs>

Advanced Techniques

For more complex analysis, you can:

  1. Combine multiple data sources - Join port metrics with trade data
  2. Create faceted visualizations - Compare across regions or time periods
  3. Add interactivity - Use Observable Plot's built-in interactions
<div className="my-8 p-6 bg-gradient-to-r from-purple-50 to-pink-50 rounded-xl"> <h3 className="text-2xl font-bold mb-4">Next Steps</h3> <p className="mb-4 text-gray-700"> Ready to dive deeper? Check out our advanced tutorials on econometric analysis and causal inference. </p> <Button>Explore Tutorials</Button> </div>

Conclusion

Modern data tools make it easier than ever to analyze complex supply chain data. With Observable Plot and Python, you can create publication-ready visualizations in minutes.

</div> ```

Presentation Setup

1. Create Layout:

hljs typescript
// app/(presentation)/layout.tsx import type { Metadata } from 'next' import { Inter } from 'next/font/google' import '@/app/globals.css' const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { title: 'Presentation', description: 'Interactive slides', } export default function PresentationLayout({ children, }: { children: React.ReactNode }) { return ( <div className={inter.className}> <main className="min-h-screen bg-gray-900"> {children} </main> </div> ) }

2. Create Slide Component:

hljs typescript
// components/presentation/Slide.tsx 'use client' import { ReactNode, useEffect, useState } from 'react' interface SlideProps { id: number children: ReactNode background?: 'white' | 'dark' | 'gradient' className?: string } export function Slide({ id, children, background = 'white', className = '' }: SlideProps) { const [currentSlide, setCurrentSlide] = useState(0) const [totalSlides, setTotalSlides] = useState(0) useEffect(() => { // Count total slides const slides = document.querySelectorAll('[data-slide]') setTotalSlides(slides.length) // Get current slide from URL hash or default to 0 const hash = window.location.hash.replace('#', '') const initialSlide = hash ? parseInt(hash) : 0 setCurrentSlide(initialSlide) // Navigate to the current slide const slide = document.querySelector(`[data-slide="${currentSlide}"]`) slide?.scrollIntoView({ behavior: 'smooth' }) // Keyboard navigation const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'ArrowRight' || e.key === ' ') { e.preventDefault() const next = Math.min(currentSlide + 1, totalSlides - 1) setCurrentSlide(next) window.location.hash = `#${next}` } else if (e.key === 'ArrowLeft') { e.preventDefault() const prev = Math.max(currentSlide - 1, 0) setCurrentSlide(prev) window.location.hash = `#${prev}` } else if (e.key === 'f') { document.documentElement.requestFullscreen() } } window.addEventListener('keydown', handleKeyDown) return () => window.removeEventListener('keydown', handleKeyDown) }, [currentSlide, totalSlides]) const bgStyles = { white: 'bg-white text-gray-900', dark: 'bg-gray-900 text-white', gradient: 'bg-gradient-to-br from-blue-600 via-purple-600 to-pink-600 text-white', } const isActive = id === currentSlide return ( <div data-slide={id} className={` min-h-screen w-full flex items-center justify-center p-12 ${bgStyles[background]} ${className} ${isActive ? 'opacity-100' : 'opacity-40'} `} > <div className="max-w-6xl w-full"> {children} <div className="absolute bottom-8 right-8 text-sm opacity-50"> {id + 1} / {totalSlides} </div> </div> </div> ) }

3. Create TwoColumn Component:

hljs typescript
// components/presentation/TwoColumn.tsx import { ReactNode } from 'react' interface TwoColumnProps { left: ReactNode right: ReactNode } export function TwoColumn({ left, right }: TwoColumnProps) { return ( <div className="grid grid-cols-2 gap-12 items-center"> <div>{left}</div> <div>{right}</div> </div> ) }

4. Create Example Presentation:

hljs mdx
// app/(presentation)/my-talk/page.mdx import { Slide } from '@/components/presentation/Slide' import { TwoColumn } from '@/components/presentation/TwoColumn' <Slide id={0} background="gradient"> <h1 className="text-7xl font-bold mb-6">Supply Chain Analytics</h1> <p className="text-3xl text-white/90">Modern Tools for Data-Driven Decisions</p> <p className="text-xl mt-12 text-white/70">Use arrow keys to navigate →</p> </Slide> <Slide id={1} background="white"> <h2 className="text-6xl font-bold mb-12">Today's Agenda</h2> <div className="text-3xl space-y-6"> <div>1. The Challenge</div> <div>2. Our Approach</div> <div>3. Results & Impact</div> <div>4. Next Steps</div> </div> </Slide> <Slide id={2} background="dark"> <TwoColumn left={ <> <h2 className="text-5xl font-bold mb-8">The Challenge</h2> <ul className="text-2xl space-y-4 text-gray-300"> <li>Complex global supply chains</li> <li>Real-time disruptions</li> <li>Limited visibility</li> <li>Reactive decision-making</li> </ul> </> } right={ <div className="p-12 bg-red-900/30 rounded-2xl border-2 border-red-500"> <div className="text-7xl font-bold text-red-400 mb-4">23%</div> <div className="text-2xl text-gray-300">Increase in disruption frequency</div> </div> } /> </Slide> <Slide id={3} background="white"> <h2 className="text-6xl font-bold mb-12">Our Solution</h2> <div className="grid grid-cols-3 gap-8"> <div className="p-8 bg-blue-50 rounded-xl"> <div className="text-5xl mb-4">📊</div> <h3 className="text-2xl font-bold mb-4">Data Integration</h3> <p className="text-gray-600">Combine multiple sources into a unified view</p> </div> <div className="p-8 bg-purple-50 rounded-xl"> <div className="text-5xl mb-4">🔍</div> <h3 className="text-2xl font-bold mb-4">Real-Time Analysis</h3> <p className="text-gray-600">Monitor performance as it happens</p> </div> <div className="p-8 bg-pink-50 rounded-xl"> <div className="text-5xl mb-4">🚀</div> <h3 className="text-2xl font-bold mb-4">Predictive Models</h3> <p className="text-gray-600">Anticipate disruptions before they occur</p> </div> </div> </Slide> <Slide id={4} background="gradient"> <TwoColumn left={ <> <h2 className="text-5xl font-bold mb-8">Key Results</h2> <div className="space-y-6"> <div className="p-6 bg-white/10 rounded-xl backdrop-blur"> <div className="text-4xl font-bold mb-2">-34%</div> <div className="text-xl">Reduction in dwell time</div> </div> <div className="p-6 bg-white/10 rounded-xl backdrop-blur"> <div className="text-4xl font-bold mb-2">+28%</div> <div className="text-xl">Improvement in on-time delivery</div> </div> <div className="p-6 bg-white/10 rounded-xl backdrop-blur"> <div className="text-4xl font-bold mb-2">$2.3M</div> <div className="text-xl">Annual cost savings</div> </div> </div> </> } right={ <div className="text-2xl leading-relaxed text-white/90"> By implementing our analytics platform, we achieved measurable improvements across all key metrics within 6 months. </div> } /> </Slide> <Slide id={5} background="dark"> <h2 className="text-6xl font-bold mb-8 text-center">Thank You</h2> <p className="text-3xl text-center text-gray-400 mb-12">Questions?</p> <div className="text-center text-xl text-gray-500"> <div>john.doe@example.com</div> <div className="mt-2">@johndoe</div> </div> </Slide>

Global Styles

Create a globals.css file with these styles:

hljs css
/* app/globals.css */ @tailwind base; @tailwind components; @tailwind utilities; @layer base { /* Import fonts */ @import url('https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,opsz,wght@0,8..60,200..900;1,8..60,200..900&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap'); /* KaTeX styles for math */ @import url('https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css'); html { scroll-behavior: smooth; } body { @apply antialiased; } } @layer components { /* Academic article styles */ .academic-article { @apply max-w-[760px] mx-auto px-6 py-12 relative; } .academic-article h1 { @apply text-5xl font-bold mb-6 leading-tight; } .academic-article h2 { @apply text-4xl font-bold mt-12 mb-6; } .academic-article h3 { @apply text-3xl font-semibold mt-8 mb-4; } .academic-article p { @apply text-[21px] leading-[1.58] mb-6 text-gray-800; } .academic-article a { @apply text-blue-600 hover:underline; } /* Blog post styles */ .blog-post { @apply max-w-4xl mx-auto px-6 py-12; } .blog-post h2 { @apply text-4xl font-bold mt-12 mb-6; } .blog-post h3 { @apply text-3xl font-semibold mt-8 mb-4; } .blog-post p { @apply text-[18px] leading-[1.75] mb-6 text-gray-700; } /* Presentation slide styles */ .presentation-slides { @apply snap-y snap-mandatory h-screen overflow-y-scroll; } .presentation-slide { @apply snap-start min-h-screen w-full flex items-center justify-center p-12; } /* Code blocks */ .prose pre { @apply bg-gray-900 text-gray-100 rounded-lg p-6 overflow-x-auto; } .prose code { @apply bg-gray-100 text-gray-900 rounded px-2 py-1 text-sm; } /* Tables */ .prose table { @apply w-full border-collapse my-8; } .prose th { @apply bg-gray-100 font-semibold p-3 text-left border-b-2 border-gray-300; } .prose td { @apply p-3 border-b border-gray-200; } } @layer utilities { .text-balance { text-wrap: balance; } }

Advanced Patterns

Adding Math Support

For LaTeX equations (academic articles):

hljs mdx
The quadratic formula is: $$ x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} $$ Inline math: $E = mc^2$

Adding Animations

For presentations with progressive disclosure:

hljs typescript
import { motion } from 'framer-motion' <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.5 }} > Content appears smoothly </motion.div>

Dark Mode Support

Add dark mode to any layout:

hljs typescript
import { ThemeProvider } from 'next-themes' export default function Layout({ children }: { children: React.ReactNode }) { return ( <ThemeProvider attribute="class" defaultTheme="system"> {children} </ThemeProvider> ) }

Custom MDX Components

Map HTML elements to custom components:

hljs typescript
// mdx-components.tsx import type { MDXComponents } from 'mdx/types' import { MarginNote } from './components/academic/MarginNote' export function useMDXComponents(components: MDXComponents): MDXComponents { return { ...components, aside: MarginNote, // Map other elements as needed } }

Metadata Configuration

For SEO and social sharing:

hljs typescript
// app/(academic)/my-article/page.tsx import type { Metadata } from 'next' export const metadata: Metadata = { title: 'Article Title | Your Site', description: 'Article description for search engines', authors: [{ name: 'Your Name' }], openGraph: { title: 'Article Title', description: 'Article description', type: 'article', publishedTime: '2024-10-01T00:00:00.000Z', }, }

Deployment

Build and Deploy

hljs bash
# Build for production npm run build # Start production server npm start # Or deploy to Vercel vercel --prod

Environment Variables

hljs bash
# .env.local NEXT_PUBLIC_SITE_URL=https://yourdomain.com

Troubleshooting

See references/troubleshooting.md for solutions to common issues.

Quick Reference

See references/quick-reference.md for copy-paste code snippets.

Examples

Complete working examples are available in the assets/ directory:

  • assets/academic/ - Full academic article example
  • assets/blog/ - Full blog post example
  • assets/presentation/ - Full presentation example

Version: 1.0.0
Last Updated: October 2024
Compatible With: Next.js 15+, React 19, TypeScript 5+

Related Categories