Building an SEO-Friendly Corporate Website from Scratch with Next.js: Step-by-Step Guide
This guide details the steps to create an SEO-friendly, performant corporate website using Next.js. From project setup to performance optimization, all stages are covered.
Creating an SEO-Friendly Corporate Website from Scratch with Next.js: A Comprehensive Guide
Table of Contents
- Project Setup
- SEO and Metadata Management
- Multi-Language Support
- Database Integration with Prisma ORM
- Performance Optimization
- Admin Panel and Content Management
- Deployment and CI/CD
1. Project Setup
When starting a project, it is essential to understand how to manage Next.js setup and dependencies.
Basic Setup
npx create-next-app@latest my-corporate-site cd my-corporate-site
Dependencies
{ "dependencies": { "@next-auth/prisma-adapter": "^1.0.7", "@prisma/client": "^5.22.0", "next": "14.0.0", "next-auth": "^4.24.10", "react": "18.2.0", "react-dom": "18.2.0", "react-quill": "^2.0.0" } }
Directory Structure and Explanations
├── app/ │ ├── [lang]/ # Language-based routing │ │ ├── page.js # Homepage │ │ ├── blog/ # Blog pages │ │ └── projects/ # Project pages │ ├── api/ # API endpoints │ └── admin/ # Admin panel ├── components/ # Reusable components ├── config/ # Configuration files └── prisma/ # Database schemas
2. SEO and Metadata Management
SEO relies heavily on metadata management, which involves creating unique titles and descriptions for each page. Creating a centralized metadata configuration with Next.js is straightforward.
Example Metadata Configuration
// config/metadata.js export const defaultMetadata = { metadataBase: new URL('https://example.com'), title: { default: "Company Name", template: "%s | Company Name" }, description: { tr: "Turkish description", en: "English description" }, alternates: { canonical: "https://example.com", languages: { 'tr-TR': '/tr', 'en-US': '/en', }, }, openGraph: { // ... OpenGraph configuration } };
You can also create dynamic metadata for each blog post to improve SEO compatibility.
Dynamic Metadata Generation
// app/[lang]/blog/[slug]/page.js export async function generateMetadata({ params }) { const post = await prisma.blog.findUnique({ where: { slug: params.slug } }); return { title: post.title, description: post.excerpt, openGraph: { title: post.title, description: post.excerpt, images: [post.coverImage] } }; }
3. Multi-Language Support
Multi-language support is crucial for corporate websites. With Next.js, managing language-based content and redirection middleware is quite simple. Redirecting users based on their language preference enhances user experience and SEO.
Language Redirection Middleware
// middleware.js export function middleware(request) { const { pathname } = request.nextUrl; const pathnameHasLocale = locales.some( locale => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}` ); if (!pathnameHasLocale) { const locale = getLocale(request); return NextResponse.redirect( new URL(`/${locale}${pathname}`, request.url) ); } }
Language-Based Content Management
// app/[lang]/page.js async function getHomeData(lang) { const hero = await prisma.hero.findFirst({ where: { cultures: { some: { code: lang } } } }); // Other content... return { hero, ... }; }
4. Database Integration with Prisma ORM
At the database layer, Prisma ORM can be used to manage blogs, projects, and cultural content. For example, you can create a multilingual blog schema and query this data using Prisma to serve language-based content.
Example Prisma Schema
// prisma/schema.prisma model Blog { id String @id @default(uuid()) slug String @unique title String content String @db.Text excerpt String? published Boolean @default(false) cultures Culture[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Culture { id String @id @default(uuid()) code String // tr, en blogs Blog[] projects Project[] }
Database Querying
// lib/prisma.js import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); export default prisma;
5. Performance Optimization
Performance is crucial for SEO and user experience. Techniques like image optimization, lazy loading, and reducing bundle size can significantly enhance site performance.
Image Optimization
// components/OptimizedImage.js import Image from 'next/image'; export function OptimizedImage({ src, alt, ...props }) { return ( <Image src={src} alt={alt} width={800} height={600} placeholder="blur" blurDataURL={`data:image/svg+xml,...`} {...props} /> ); }
This ensures faster loading pages, positively impacting your SEO ranking.
Font Optimization
// app/layout.js const geistSans = localFont({ src: "./fonts/GeistVF.woff", variable: "--font-geist-sans", weight: "100 900", }); export default function RootLayout({ children }) { return ( <html lang="en"> <body className={geistSans.variable}> {children} </body> </html> ); }
6. Admin Panel and Content Management
To easily manage your content, create secure admin routes for the admin panel. Additionally, create content management APIs to dynamically update site content.
Secure Admin Routes
// middleware.js export const config = { matcher: [ '/admin/:path*', '/api/admin/:path*' ] } export async function middleware(request) { const session = await getSession(request); if (!session) { return NextResponse.redirect(new URL('/auth/signin', request.url)); } if (!session.user.isAdmin) { return NextResponse.redirect(new URL('/', request.url)); } }
Content Management APIs
// app/api/admin/blog/route.js export async function POST(request) { const session = await getServerSession(); if (!session?.user?.isAdmin) { return new Response('Unauthorized', { status: 401 }); } const data = await request.json(); const blog = await prisma.blog.create({ data: { title: data.title, content: data.content, cultures: { connect: data.cultures.map(code => ({ code })) } } }); return Response.json(blog); }
7. Deployment and CI/CD
You can easily deploy your Next.js application using Vercel and automate your CI/CD processes using GitHub Actions. This ensures that your code updates are published instantly and continuously integrated.
Vercel Deployment Configuration
// vercel.json { "version": 2, "builds": [ { "src": "package.json", "use": "@vercel/next" } ], "env": { "DATABASE_URL": "@database_url", "NEXTAUTH_SECRET": "@nextauth_secret" } }
Automatic Deployment with GitHub Actions
# .github/workflows/deploy.yml name: Deploy on: push: branches: [ main ] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Deploy to Vercel uses: amondnet/vercel-action@v20 with: vercel-token: ${{ secrets.VERCEL_TOKEN }} vercel-org-id: ${{ secrets.ORG_ID}} vercel-project-id: ${{ secrets.PROJECT_ID}}
Key Tips and Best Practices
- SEO Optimization
- Use unique titles and descriptions for each page
- Use semantic HTML
- Implement structured data (JSON-LD)
- Include Sitemap.xml and robots.txt files
- Performance
- Image optimization
- Code splitting
- Bundle size optimization
- Lazy loading
- Server-side caching
- Security
- API rate limiting
- Input validation
- CSRF protection
- Secure headers
- Management of environment variables
- Maintainability
- Modular code structure
- TypeScript usage
- ESLint and Prettier configuration
- Unit and integration tests
Conclusion
In this guide, we explored in detail how to create a modern corporate website. Using the App Router, Server Components, and other features provided by Next.js 14, we built a performant and SEO-friendly website.
Key points to consider:
- Planning an SEO strategy from the beginning
- Proper implementation of multi-language support
- Continuous monitoring of performance optimizations
- Implementing comprehensive security measures
- Creating a maintainable and scalable code base
By following this guide, you can create a modern, performant, and SEO-friendly corporate website that meets web standards.