This content originally appeared on DEV Community and was authored by gerry leo nugroho
Welcome Back, Fellow Builders! After laying the foundation in our project initialization, we’re now ready to shape the heart of our blog with configuration files. This step is where the magic happens—turning our raw tech stack into a finely tuned machine. We’ll configure Next.js 15.1.7
to handle MDX content and modern typography, set up Tailwind CSS 4.x.x
for sleek styling.
These files are:
next.config.ts
postcss.config.mjs
tailwind.config.js
And one file to import the default tailwind to out styling.
src/app/globals.css
So let’s dive in with precision and flair.
Step 1: Next.js Configuration with next.config.ts
First up is next.config.ts
, the command center for our Next.js app. This file lets us customize how Next.js compiles, bundles, and serves our blog, and we’ll spice it up with MDX support, modern features, and a custom Webpack config for advanced use cases. Based on our package.json
, we’re running Next.js 15.1.7, so let’s ensure our setup leverages its latest goodies—like the Rust-based MDX compiler and a touch of Webpack magic.
// next.config.ts
import mdx from '@next/mdx';
import UnpluginFonts from 'unplugin-fonts/webpack';
// Enable MDX support with Next.js
const withMDX = mdx({
extension: /\.mdx?$/, // Support both .md and .mdx files
options: {
remarkPlugins: [], // Add remark plugins here if needed
rehypePlugins: [] // Add rehype plugins here if needed
}
});
/** @type {import('next').NextConfig} */
const nextConfig = {
// Specify file extensions Next.js should recognize
pageExtensions: ['ts', 'tsx', 'md', 'mdx'],
// Experimental features for Next.js 15.x.x
experimental: {
mdxRs: true, // Use Rust-based MDX compiler for faster builds
reactCompiler: false // Integrate React 19 compiler for optimized rendering, but we put false value for the time being.
},
// Custom Webpack configuration for advanced use cases
webpack: (config, { isServer }) => {
// Add unplugin-fonts to Webpack for Google Fonts integration
config.plugins.push(
UnpluginFonts({
google: {
families: [
'Inter:400,700', // Sleek sans-serif for general text
'Merriweather:300,400' // Elegant serif for headings
]
}
})
);
// Example: Add custom loader for specific file types (e.g., SVGs)
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack'] // Requires `npm install @svgr/webpack` if used
});
// Optimize server-side vs client-side builds
if (!isServer) {
config.optimization.splitChunks = {
chunks: 'all', // Enable code splitting for better caching
};
}
return config;
}
};
// Export the configuration with MDX support
export default withMDX(nextConfig);
What’s Happening Here?
-
MDX Integration: The
@next/mdx
plugin lets us write blog posts in MDX, blending Markdown with JSX. We’ve set it to recognize both.md
and.mdx
files for flexibility. -
Experimental Features:
mdxRs
swaps the default MDX compiler for a Rust-based one—faster builds, happier devs.reactCompiler
taps into Next.js 15’s integration with React 19’s compiler, optimizing our components automatically. -
Custom Webpack: We’ve added
unplugin-fonts/webpack
to load Google Fonts efficiently. The Webpack config also includes a placeholder for SVG handling (install@svgr/webpack
if needed) and a server-side optimization tweak—demonstrating how to extend Next.js for advanced scenarios. -
TypeScript: Written in
.ts
for type safety, matching your TypeScript-enabled project.
This file ensures our blog is fast, font-ready, and future-proof.
Step 2: PostCSS Configuration with postcss.config.mjs
Next, we tackle postcss.config.mjs
. Since we’re using Tailwind CSS 4.0.8 with @tailwindcss/postcss
, PostCSS is our CSS processor of choice. This config ties Tailwind into our build pipeline, ensuring our styles are processed efficiently. If the file is not available already, please create one in the root of your project folder, give it a name postcss.config.mjs
and fill-up the value as per the following:
Here’s the setup:
// postcss.config.mjs
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
'@tailwindcss/postcss': {}, // Tailwind CSS 4 integration
// autoprefixer: {}, // Adds vendor prefixes for broader browser support
},
};
export default config;
Why This Matters
-
Tailwind Plugin: The
@tailwindcss/postcss
entry hooks Tailwind into PostCSS, enabling its utility-first magic. Since we installed it manually (npm install tailwindcss@4.x.x @tailwindcss/postcss postcss
), this ensures we’re running the latest version. -
Autoprefixer: This bonus plugin adds prefixes (e.g.,
-webkit-
) to CSS properties, ensuring our blog looks flawless across browsers like Chrome, Firefox, and Safari.
Place this file in your blog/
root alongside next.config.mjs
. It’s a small but mighty piece of the puzzle.
Step 3: Tailwind CSS Configuration: Styling with Elegance
Now, let’s configure Tailwind CSS in tailwind.config.js
. This file defines our design system—fonts, colors, and plugins—while embracing Tailwind 4.x.x’s CSS-first approach. Here’s the detailed setup:
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
// Specify where Tailwind should look for classes
content: [
"./src/**/*.{ts,tsx,md,mdx}", // Default content directory
"./src/pages/**/*.{ts,tsx,md,mdx}", // Legacy pages directory (if used)
"./src/components/**/*.{ts,tsx}", // Reusable components
"./src/app/**/*.{ts,tsx}", // App Router files
],
theme: {
extend: {
// Custom font families from Google Fonts
fontFamily: {
sans: ["Inter", "sans-serif"], // Clean, modern sans-serif
serif: ["Merriweather", "serif"], // Elegant serif for prose
},
// Gradient colors for a sleek, modern design
colors: {
gradientStart: "#4f46e5", // Indigo for vibrant gradients
gradientEnd: "#9333ea", // Purple for a trendy finish
},
// Customize typography plugin for blog content
typography: (theme) => ({
DEFAULT: {
css: {
color: theme("colors.gray.800"), // Readable text in light mode
"h1, h2, h3": {
fontFamily: theme("fontFamily.serif"), // Serif headings for flair
},
},
},
dark: {
css: {
color: theme("colors.gray.200"), // Crisp text in dark mode
},
},
}),
},
},
// Enable Tailwind plugins
plugins: [
require("@tailwindcss/typography"), // Beautiful prose styling
],
// Use class-based dark mode
darkMode: "class",
};
Breaking It Down
-
Content: We tell Tailwind where to look for classes—our
src/
directory covers components, App Router pages, and any legacypages/
. This ensures purging works efficiently in production. -
Theme Extensions:
-
Fonts: We sync with
unplugin-fonts
by definingInter
for body text andMerriweather
for headings—modern and readable. -
Colors: Custom gradient colors (
gradientStart
andgradientEnd
) give our blog a trendy, sleek vibe. -
Typography: The
@tailwindcss/typography
plugin gets a tweak—light and dark mode text colors, plus serif headings for a polished look.
-
Fonts: We sync with
-
Plugins: Adding
@tailwindcss/typography
ensures our MDX blog posts render beautifully with sensible defaults. -
Dark Mode: The
class
strategy integrates withnext-themes
for seamless light/dark switching.
Save this as tailwind.config.js
in your blog/
root. It’s our design foundation.
Step 4: Global CSS: Setting the Stage with Tailwind
Finally, let’s craft src/globals.css
to apply Tailwind’s base styles and define custom variables for theming. This file lives in src/styles/
(create the folder if it’s not there yet):
/* src/globals.css */
@tailwind base; /* Reset and base styles */
@tailwind components; /* Custom components (if needed later) */
@tailwind utilities; /* Utility classes */
/* Custom CSS variables for theming */
@layer base {
:root {
--bg-color: #ffffff; /* Light mode background */
--text-color: #1f2937; /* Light mode text */
--card-bg: #f9fafb; /* Light mode card background */
}
.dark {
--bg-color: #1f2937; /* Dark mode background */
--text-color: #d1d5db; /* Dark mode text */
--card-bg: #374151; /* Dark mode card background */
}
/* Apply variables globally */
body {
@apply bg-[var(--bg-color)] text-[var(--text-color)]; /* Dynamic theming */
font-family: 'Inter', sans-serif; /* Default font */
}
}
What’s Going On?
-
Tailwind Directives:
@tailwind base
resets browser styles,@tailwind components
is a placeholder for custom components (we’ll use it later), and@tailwind utilities
brings in all those handy classes. -
CSS Variables: Inside
@layer base
, we define--bg-color
,--text-color
, and--card-bg
for light and dark modes. The.dark
class toggles these values whennext-themes
applies thedark
class to<html>
. -
Body Styling: Using
@apply
, we dynamically set the background and text colors with our variables, ensuring a cohesive look. Thefont-family
defaults toInter
for consistency.
This file ties Tailwind to our app—create src/styles/
and save it there.
Step 5: Testing the Configuration
To verify, update src/app/page.tsx
to use our styles:
export default function Home() {
return (
<div className="to-light-blue-500 mt-20 bg-gradient-to-r from-cyan-400 p-20">
<h1 className="bg-clip-text text-center font-mono text-9xl text-cyan-700">
Welcome to My Blog
</h1>
</div>
);
}
Run the following command in your terminal
npm run dev --turbopack
Next fire-up your browser of choice, and visit [http://localhost:3000](http://localhost:3000)
. You should see a gradient-styled heading in Mono-font
—proof our configs are humming along.
Step 6: Wrapping Up Configuration
There you have it! We’ve configured Next.js 15.1.7 to handle MDX
and fonts, set up PostCSS for Tailwind CSS 4.x.x, defined a sleek design system, and applied global styles—all tailored to our project requirements. These files are the backbone of our blog, ensuring it’s fast, stylish, and feature-ready. Next, we’ll venture more for the structure of our project folders—I’ll see you there soon!
This content originally appeared on DEV Community and was authored by gerry leo nugroho