2025-07-21 by Remi Kristelijn
This developer guide provides comprehensive information for developers who want to contribute to, extend, or maintain the Next.js blog. Whether you're adding new features, fixing bugs, or customizing the application, this guide will help you understand the codebase and development workflow.
1# Clone the repository 2git clone <your-repo-url> 3cd next-blog 4 5# Install dependencies 6npm install 7 8# Start development server 9npm run dev
1npm run dev # Start development server 2npm run build # Build for production 3npm run start # Start production server 4npm run lint # Run ESLint 5npm run type-check # Run TypeScript type checking 6npm run ci:build # Build for Cloudflare deployment
src/
├── app/ # Next.js App Router pages
├── components/ # Reusable UI components
├── content/ # Blog content (MDX files)
├── lib/ # Utility functions and data layer
└── types/ # TypeScript type definitions
src/app/layout.tsx: Root layout with theme and error boundarysrc/lib/posts.ts: Data layer for blog postssrc/types/index.ts: TypeScript interfacesnext.config.ts: Next.js configurationwrangler.jsonc: Cloudflare deployment configuration1# Create a new branch 2git checkout -b feature/new-feature 3 4# Make your changes 5# Test locally with npm run dev 6 7# Commit your changes 8git add . 9git commit -m "feat: add new feature" 10 11# Push to remote 12git push origin feature/new-feature
Before submitting changes:
1# Run type checking 2npm run type-check 3 4# Run linting 5npm run lint 6 7# Build the project 8npm run build
1// src/components/NewComponent.tsx 2import { Box, Typography } from '@mui/material'; 3import type { NewComponentProps } from '@/types'; 4 5export default function NewComponent({ title, content }: NewComponentProps) { 6 return ( 7 <Box sx={{ p: 2 }}> 8 <Typography variant="h6" gutterBottom> 9 {title} 10 </Typography> 11 <Typography variant="body1"> 12 {content} 13 </Typography> 14 </Box> 15 ); 16}
1// src/types/index.ts 2export interface NewComponentProps { 3 title: string; 4 content: string; 5 optional?: boolean; 6}
src/content/posts/1--- 2title: "Your Post Title" 3date: "YYYY-MM-DD" 4excerpt: "Brief description of your post" 5---
1// src/lib/posts.ts 2export function getPostsByCategory(category: string): Post[] { 3 const allPosts = getAllPosts(); 4 return allPosts.filter(post => post.category === category); 5} 6 7export function searchPosts(query: string): Post[] { 8 const allPosts = getAllPosts(); 9 return allPosts.filter(post => 10 post.title.toLowerCase().includes(query.toLowerCase()) || 11 post.content.toLowerCase().includes(query.toLowerCase()) 12 ); 13}
1// src/lib/theme.ts 2export const theme = createTheme({ 3 palette: { 4 primary: { 5 main: '#1976d2', 6 light: '#42a5f5', 7 dark: '#1565c0', 8 }, 9 secondary: { 10 main: '#dc004e', 11 }, 12 }, 13 typography: { 14 fontFamily: [ 15 '-apple-system', 16 'BlinkMacSystemFont', 17 '"Segoe UI"', 18 'Roboto', 19 'sans-serif', 20 ].join(','), 21 }, 22 components: { 23 MuiButton: { 24 styleOverrides: { 25 root: { 26 textTransform: 'none', 27 }, 28 }, 29 }, 30 }, 31});
1// src/components/Search.tsx 2import { useState } from 'react'; 3import { TextField, Box } from '@mui/material'; 4import { searchPosts } from '@/lib/posts'; 5 6export default function Search() { 7 const [query, setQuery] = useState(''); 8 const [results, setResults] = useState([]); 9 10 const handleSearch = (value: string) => { 11 setQuery(value); 12 const searchResults = searchPosts(value); 13 setResults(searchResults); 14 }; 15 16 return ( 17 <Box> 18 <TextField 19 value={query} 20 onChange={(e) => handleSearch(e.target.value)} 21 placeholder="Search posts..." 22 fullWidth 23 /> 24 {/* Display results */} 25 </Box> 26 ); 27}
1// src/components/OptimizedImage.tsx 2import Image from 'next/image'; 3 4interface OptimizedImageProps { 5 src: string; 6 alt: string; 7 width: number; 8 height: number; 9} 10 11export default function OptimizedImage({ src, alt, width, height }: OptimizedImageProps) { 12 return ( 13 <Image 14 src={src} 15 alt={alt} 16 width={width} 17 height={height} 18 placeholder="blur" 19 blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCdABmX/9k=" 20 /> 21 ); 22}
1// src/app/about/page.tsx 2import { Container, Typography, Box } from '@mui/material'; 3import Navigation from '@/components/Navigation'; 4 5export default function AboutPage() { 6 return ( 7 <Box sx={{ minHeight: '100vh', display: 'flex', flexDirection: 'column' }}> 8 <Navigation title="About" showHome={true} showBack={false} /> 9 <Container maxWidth="md" sx={{ flex: 1, py: 4 }}> 10 <Typography variant="h3" component="h1" gutterBottom> 11 About Us 12 </Typography> 13 <Typography variant="body1"> 14 Your about page content here... 15 </Typography> 16 </Container> 17 </Box> 18 ); 19}
1// __tests__/components/PostCard.test.tsx 2import { render, screen } from '@testing-library/react'; 3import PostCard from '@/components/PostCard'; 4 5const mockPost = { 6 id: 'test-post', 7 title: 'Test Post', 8 excerpt: 'Test excerpt', 9 date: '2024-01-25', 10 slug: 'test-post', 11 content: 'Test content', 12}; 13 14describe('PostCard', () => { 15 it('renders post title and excerpt', () => { 16 render(<PostCard post={mockPost} />); 17 18 expect(screen.getByText('Test Post')).toBeInTheDocument(); 19 expect(screen.getByText('Test excerpt')).toBeInTheDocument(); 20 }); 21});
1# Analyze bundle size 2npm run build 3# Check the .next/analyze directory for bundle analysis
1// src/lib/performance.ts 2export function measurePerformance(name: string, fn: () => void) { 3 const start = performance.now(); 4 fn(); 5 const end = performance.now(); 6 console.log(`${name} took ${end - start} milliseconds`); 7}
1# Build for production 2npm run build 3 4# Test production build 5npm run start
1# Build for Cloudflare 2npm run ci:build 3 4# Deploy to Cloudflare Pages 5npm run deploy
1# Clear Next.js cache 2rm -rf .next 3npm run build
1# Check TypeScript configuration 2npx tsc --noEmit
1# Clear npm cache 2npm cache clean --force 3rm -rf node_modules package-lock.json 4npm install
1# Kill all Node processes 2pkill -f "next dev" 3npm run dev
This developer guide provides a comprehensive overview of how to contribute to and extend your Next.js blog. By following these guidelines, you can maintain code quality, add new features safely, and ensure the application continues to meet high standards of performance and accessibility.
Remember to:
The modular architecture and clear separation of concerns make it easy to add new features while maintaining the overall quality and performance of the application.
Happy coding! Your contributions help make the blog better for everyone.