Next.js Development
Development conventions and patterns for the kimmoihanus.com Next.js site.
When to Use
- Creating new pages or components
- Working with API routes
- Styling with Tailwind CSS
- Working with MDX content
Project Structure
/
├── components/ # React components
├── css/ # Stylesheets (Tailwind, Prism)
├── graphics/ # Graphics markdown files
├── lib/ # Utility functions and hooks
├── pages/ # Next.js pages (file-based routing)
│ ├── api/ # API routes
│ ├── graphics/ # Dynamic graphics pages
│ └── posts/ # Dynamic post pages
├── posts/ # Blog post markdown files
├── prose/ # Static prose content
├── public/ # Static assets
└── tools/ # Additional tools and MCP servers
Conventions
Pages
- Pages use file-based routing in
/pages/ - Dynamic routes use
[slug].jsformat - API routes go in
/pages/api/
Components
- Components are in
/components/ - Use functional components with hooks
- Export default the main component
Styling
- Use Tailwind CSS classes
- Custom styles in
/css/directory - Module CSS for component-specific styles (e.g.,
graphics.module.css)
Content
- Blog posts:
/posts/XXX-slug.md - Graphics:
/graphics/slug.md - Static prose:
/prose/slug.md
Key Libraries
next- Frameworknext-seo- SEO configurationnext-mdx-remote- MDX renderingtailwindcss- Stylinggray-matter- Frontmatter parsing
Development Commands
bash1# Start development server 2npm run dev 3 4# Build for production 5npm run build 6 7# Start production server 8npm run start 9 10# Generate sitemap 11npm run postbuild
Creating New Pages
- Add file to
/pages/directory - Export a default React component
- Optionally export
getStaticPropsorgetServerSideProps
Example:
jsx1import Layout from '../components/Layout'; 2import { NextSeo } from 'next-seo'; 3 4export default function MyPage() { 5 return ( 6 <Layout> 7 <NextSeo title="My Page" /> 8 <h1>My New Page</h1> 9 </Layout> 10 ); 11}
Creating API Routes
Add file to /pages/api/:
js1export default async function handler(req, res) { 2 if (req.method !== 'POST') { 3 return res.status(405).json({ error: 'Method not allowed' }); 4 } 5 6 // Your logic here 7 res.status(200).json({ success: true }); 8}
Working with MDX Content
Use the lib functions:
js1import { getPostBySlug, getAllPosts } from '../lib/posts'; 2import { serialize } from 'next-mdx-remote/serialize';